[haiku-commits] r35812 - haiku/trunk/src/system/boot/loader

  • From: ingo_weinhold@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 11 Mar 2010 18:09:12 +0100 (CET)

Author: bonefish
Date: 2010-03-11 18:09:11 +0100 (Thu, 11 Mar 2010)
New Revision: 35812
Changeset: http://dev.haiku-os.org/changeset/35812/haiku

Added:
   haiku/trunk/src/system/boot/loader/pager.cpp
   haiku/trunk/src/system/boot/loader/pager.h
Log:
A simple pager implemented on top of the generic text console interface.


Added: haiku/trunk/src/system/boot/loader/pager.cpp
===================================================================
--- haiku/trunk/src/system/boot/loader/pager.cpp                                
(rev 0)
+++ haiku/trunk/src/system/boot/loader/pager.cpp        2010-03-11 17:09:11 UTC 
(rev 35812)
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2010, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+
+
+#include "pager.h"
+
+#include <ctype.h>
+#include <string.h>
+
+#include <algorithm>
+
+#include <boot/platform/generic/text_console.h>
+
+
+// #pragma mark - PagerTextSource
+
+
+PagerTextSource::~PagerTextSource()
+{
+}
+
+
+// #pragma mark -
+
+
+static size_t
+next_line(const PagerTextSource& textSource, size_t width, size_t offset,
+       char* buffer, size_t bufferSize)
+{
+       size_t bytesRead = textSource.Read(offset, buffer, bufferSize - 1);
+       if (bytesRead == 0)
+               return 0;
+
+       buffer[bytesRead] = '\0';
+
+       // replace all '\0's by spaces
+       for (size_t i = 0; i < bytesRead; i++) {
+               if (buffer[i] == '\0')
+                       buffer[i] = ' ';
+       }
+
+       if (const char* lineEnd = strchr(buffer, '\n'))
+               bytesRead = lineEnd - buffer;
+
+       if (bytesRead > (size_t)width)
+               bytesRead = width;
+
+       // replace unprintables by '.'
+       for (size_t i = 0; i < bytesRead; i++) {
+               if (!isprint(buffer[i]))
+                       buffer[i] = '.';
+       }
+
+       bool lineBreak = buffer[bytesRead] == '\n';
+
+       buffer[bytesRead] = '\0';
+
+       return bytesRead + (lineBreak ? 1 : 0);
+}
+
+
+static int32
+count_lines(const PagerTextSource& textSource, size_t width, char* buffer,
+       size_t bufferSize)
+{
+       int32 lineCount = 0;
+       size_t offset = 0;
+
+       while (true) {
+               size_t bytesRead = next_line(textSource, width, offset, buffer,
+                       bufferSize);
+               if (bytesRead == 0)
+                       break;
+
+               offset += bytesRead;
+               lineCount++;
+       }
+
+       return lineCount;
+}
+
+
+static size_t
+offset_of_line(const PagerTextSource& textSource, size_t width, char* buffer,
+       size_t bufferSize, int32 line)
+{
+       int32 lineCount = 0;
+       size_t offset = 0;
+
+       while (true) {
+               if (line == lineCount)
+                       return offset;
+
+               size_t bytesRead = next_line(textSource, width, offset, buffer,
+                       bufferSize);
+               if (bytesRead == 0)
+                       break;
+
+               offset += bytesRead;
+               lineCount++;
+       }
+
+       return offset;
+}
+
+
+// #pragma mark -
+
+
+void
+pager(const PagerTextSource& textSource)
+{
+       console_set_cursor(0, 0);
+
+       int32 width = console_width();
+       int32 height = console_height();
+
+       char lineBuffer[256];
+
+       int32 lineCount = count_lines(textSource, width, lineBuffer,
+               sizeof(lineBuffer));
+       int32 topLine = 0;
+
+       bool quit = false;
+       while (!quit) {
+               // get the text offset for the top line
+               size_t offset = offset_of_line(textSource, width, lineBuffer,
+                       sizeof(lineBuffer), topLine);
+
+               // clear the screen and print the lines
+               console_clear_screen();
+
+               int32 screenLine = 0;
+               while (screenLine + 1 < height) {
+                       size_t bytesRead = next_line(textSource, width, offset, 
lineBuffer,
+                               sizeof(lineBuffer));
+                       if (bytesRead == 0)
+                               break;
+
+                       console_set_cursor(0, screenLine);
+                       puts(lineBuffer);
+
+                       offset += bytesRead;
+                       screenLine++;
+               }
+
+               // print the statistics line at the bottom
+               console_set_cursor(0, height - 1);
+               console_set_color(BLACK, WHITE);
+               int32 bottomLine = std::min(topLine + height - 2, lineCount - 
1);
+               printf("%" B_PRIuSIZE " - %" B_PRIuSIZE "  %" B_PRIuSIZE "%%",
+                       topLine, bottomLine, (bottomLine + 1) * 100 / 
lineCount);
+               console_set_color(WHITE, BLACK);
+
+               // wait for a key that changes the position
+               int32 previousTopLine = topLine;
+
+               while (!quit && topLine == previousTopLine) {
+                       switch (console_wait_for_key()) {
+                               case TEXT_CONSOLE_KEY_ESCAPE:
+                               case 'q':
+                               case 'Q':
+                                       // quit
+                                       quit = true;
+                                       break;
+
+                               case TEXT_CONSOLE_KEY_DOWN:
+                               case TEXT_CONSOLE_KEY_RETURN:
+                                       // next line
+                                       topLine++;
+                                       break;
+
+                               case TEXT_CONSOLE_KEY_UP:
+                                       // previous line
+                                       topLine--;
+                                       break;
+
+                               case TEXT_CONSOLE_KEY_PAGE_UP:
+                                       // previous page
+                                       topLine -= height - 1;
+                                       break;
+
+                               case TEXT_CONSOLE_KEY_PAGE_DOWN:
+                                       // next page
+                                       topLine += height - 1;
+                                       break;
+
+                               case TEXT_CONSOLE_KEY_HOME:
+                                       // beginning of text
+                                       topLine = 0;
+                                       break;
+
+                               case TEXT_CONSOLE_KEY_END:
+                                       // end of text
+                                       topLine = lineCount;
+                                       break;
+                       }
+
+                       if (topLine > lineCount - (height - 1))
+                               topLine = lineCount - (height - 1);
+                       if (topLine < 0)
+                               topLine = 0;
+               }
+       }
+}

Added: haiku/trunk/src/system/boot/loader/pager.h
===================================================================
--- haiku/trunk/src/system/boot/loader/pager.h                          (rev 0)
+++ haiku/trunk/src/system/boot/loader/pager.h  2010-03-11 17:09:11 UTC (rev 
35812)
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2010, Ingo Weinhold, ingo_weinhold@xxxxxxx
+ * Distributed under the terms of the MIT License.
+ */
+#ifndef PAGER_H
+#define PAGER_H
+
+
+#include <SupportDefs.h>
+
+
+class PagerTextSource {
+public:
+       virtual                                         ~PagerTextSource();
+
+       virtual size_t                          BytesAvailable() const = 0;
+       virtual size_t                          Read(size_t offset, void* 
buffer,
+                                                                       size_t 
size) const = 0;
+};
+
+
+void   pager(const PagerTextSource& textSource);
+
+
+#endif // PAGER_H


Other related posts:

  • » [haiku-commits] r35812 - haiku/trunk/src/system/boot/loader - ingo_weinhold