/*
* Copyright 2010, Ingo Weinhold, ingo_weinhold@gmx.de.
* 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, GRAY);
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;
}
}
}
↑ V576 Incorrect format. Consider checking the fourth actual argument of the 'printf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the third actual argument of the 'printf' function. The memsize type argument is expected.
↑ V576 Incorrect format. Consider checking the second actual argument of the 'printf' function. The memsize type argument is expected.