* Based on ahwayakchih's blue screen paging code (see bug #1444), I added

paging support to KDL (but not the on-screen debug output for now).
* Defaults to "on", use the new "paging" KDL command to turn it off (or on
  again).
* When pressing 'q' while it is waiting for a key, it will now eat the rest
  of the commands output (helpful for slow screen output of a large data set).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23566 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2008-01-16 20:39:00 +00:00
parent b9074efcb7
commit 855ab2b312
3 changed files with 126 additions and 23 deletions
+108 -22
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2005-2007, Axel Dörfler, [email protected]. All rights reserved.
* Copyright 2005-2008, Axel Dörfler, [email protected]. All rights reserved.
* Distributed under the terms of the MIT License.
*/
@@ -14,6 +14,8 @@
#include <string.h>
#include <stdio.h>
#include "debug_commands.h"
#define USE_SCROLLING 0
#define NO_CLEAR 1
@@ -44,6 +46,9 @@ struct screen_info {
uint8 attr;
bool bright_attr;
bool reverse_attr;
int32 in_command_rows;
bool paging;
bool ignore_output;
// state machine
console_state state;
@@ -79,8 +84,9 @@ move_cursor(int32 x, int32 y)
#if USE_SCROLLING
/** scroll from the cursor line up to the top of the scroll region up one line */
/*! Scroll from the cursor line up to the top of the scroll region up one
line.
*/
static void
scroll_up(void)
{
@@ -96,18 +102,51 @@ scroll_up(void)
static void
next_line(void)
{
if (in_command_invocation())
sScreen.in_command_rows++;
else
sScreen.in_command_rows = 0;
if (sScreen.y == sScreen.rows - 1) {
#if USE_SCROLLING
scroll_up();
#else
if (sScreen.paging && sScreen.in_command_rows > 1) {
// We're in the debugger, and a command is being executed
const char *text = "Press key to continue, Q to quit";
int32 length = strlen(text);
if (sScreen.x + length > sScreen.columns) {
// make sure we don't overwrite too much
text = "P";
length = 1;
}
for (int32 i = 0; i < length; i++) {
sModule->put_glyph(sScreen.columns - length + i, sScreen.y,
text[i], 0xf0);
}
char c = blue_screen_getchar();
if (c == 'q')
sScreen.ignore_output = true;
// remove on screen text again
sModule->fill_glyph(sScreen.columns - length, sScreen.y, length,
1, ' ', sScreen.attr);
}
sScreen.y = 0;
sModule->fill_glyph(0, 0, sScreen.columns, 2, ' ', sScreen.attr);
#endif
} else if (sScreen.y < sScreen.rows - 1) {
sScreen.y++;
}
#if NO_CLEAR
sModule->fill_glyph(0, (sScreen.y + 2) % sScreen.rows, sScreen.columns, 1, ' ', sScreen.attr);
if (sScreen.y + 2 < sScreen.rows) {
sModule->fill_glyph(0, (sScreen.y + 2) % sScreen.rows, sScreen.columns,
1, ' ', sScreen.attr);
}
#endif
sScreen.x = 0;
}
@@ -118,14 +157,16 @@ erase_line(erase_line_mode mode)
{
switch (mode) {
case LINE_ERASE_WHOLE:
sModule->fill_glyph(0, sScreen.y, sScreen.columns, 1, ' ', sScreen.attr);
sModule->fill_glyph(0, sScreen.y, sScreen.columns, 1, ' ',
sScreen.attr);
break;
case LINE_ERASE_LEFT:
sModule->fill_glyph(0, sScreen.y, sScreen.x + 1, 1, ' ', sScreen.attr);
sModule->fill_glyph(0, sScreen.y, sScreen.x + 1, 1, ' ',
sScreen.attr);
break;
case LINE_ERASE_RIGHT:
sModule->fill_glyph(sScreen.x, sScreen.y, sScreen.columns - sScreen.x,
1, ' ', sScreen.attr);
sModule->fill_glyph(sScreen.x, sScreen.y, sScreen.columns
- sScreen.x, 1, ' ', sScreen.attr);
break;
// default:
}
@@ -186,7 +227,8 @@ set_vt100_attributes(int32 *args, int32 argCount)
break;
case 7: // reverse
sScreen.reverse_attr = true;
sScreen.attr = ((sScreen.attr & BMASK) >> 4) | ((sScreen.attr & FMASK) << 4);
sScreen.attr = ((sScreen.attr & BMASK) >> 4)
| ((sScreen.attr & FMASK) << 4);
if (sScreen.bright_attr)
sScreen.attr |= 0x08;
break;
@@ -194,14 +236,20 @@ set_vt100_attributes(int32 *args, int32 argCount)
break;
/* foreground colors */
case 30: sScreen.attr = (sScreen.attr & ~FMASK) | 0 | (sScreen.bright_attr ? 0x08 : 0); break; // black
case 31: sScreen.attr = (sScreen.attr & ~FMASK) | 4 | (sScreen.bright_attr ? 0x08 : 0); break; // red
case 32: sScreen.attr = (sScreen.attr & ~FMASK) | 2 | (sScreen.bright_attr ? 0x08 : 0); break; // green
case 33: sScreen.attr = (sScreen.attr & ~FMASK) | 6 | (sScreen.bright_attr ? 0x08 : 0); break; // yellow
case 34: sScreen.attr = (sScreen.attr & ~FMASK) | 1 | (sScreen.bright_attr ? 0x08 : 0); break; // blue
case 35: sScreen.attr = (sScreen.attr & ~FMASK) | 5 | (sScreen.bright_attr ? 0x08 : 0); break; // magenta
case 36: sScreen.attr = (sScreen.attr & ~FMASK) | 3 | (sScreen.bright_attr ? 0x08 : 0); break; // cyan
case 37: sScreen.attr = (sScreen.attr & ~FMASK) | 7 | (sScreen.bright_attr ? 0x08 : 0); break; // white
case 30: // black
case 31: // red
case 32: // green
case 33: // yellow
case 34: // blue
case 35: // magenta
case 36: // cyan
case 37: // white
{
const uint8 colors[] = {0, 4, 2, 6, 1, 5, 3, 7};
sScreen.attr = (sScreen.attr & ~FMASK) | colors[args[i] - 30]
| (sScreen.bright_attr ? 0x08 : 0);
break;
}
/* background colors */
case 40: sScreen.attr = (sScreen.attr & ~BMASK) | (0 << 4); break; // black
@@ -415,7 +463,8 @@ parse_character(char c)
break;
default:
sScreen.args[sScreen.arg_count] = 0;
process_vt100_command(c, false, sScreen.args, sScreen.arg_count + 1);
process_vt100_command(c, false, sScreen.args,
sScreen.arg_count + 1);
sScreen.state = CONSOLE_STATE_NORMAL;
}
break;
@@ -427,10 +476,12 @@ parse_character(char c)
sScreen.state = CONSOLE_STATE_PARSING_ARG;
break;
case '?':
// private DEC mode parameter follows - we ignore those anyway
// private DEC mode parameter follows - we ignore those
// anyway
break;
default:
process_vt100_command(c, true, sScreen.args, sScreen.arg_count + 1);
process_vt100_command(c, true, sScreen.args,
sScreen.arg_count + 1);
sScreen.state = CONSOLE_STATE_NORMAL;
}
break;
@@ -446,7 +497,8 @@ parse_character(char c)
sScreen.state = CONSOLE_STATE_PARSING_ARG;
break;
default:
process_vt100_command(c, true, sScreen.args, sScreen.arg_count + 1);
process_vt100_command(c, true, sScreen.args,
sScreen.arg_count + 1);
sScreen.state = CONSOLE_STATE_NORMAL;
}
break;
@@ -461,13 +513,36 @@ parse_character(char c)
sScreen.state = CONSOLE_STATE_NEW_ARG;
break;
default:
process_vt100_command(c, true, sScreen.args, sScreen.arg_count + 1);
process_vt100_command(c, true, sScreen.args,
sScreen.arg_count + 1);
sScreen.state = CONSOLE_STATE_NORMAL;
}
}
}
static int
set_paging(int argc, char **argv)
{
if (argc > 1 && !strcmp(argv[1], "--help")) {
kprintf("usage: %s [on|off]\n", argv[0]);
return 0;
}
if (argc == 1)
sScreen.paging = !sScreen.paging;
else if (!strcmp(argv[1], "on"))
sScreen.paging = true;
else if (!strcmp(argv[1], "off"))
sScreen.paging = false;
else
sScreen.paging = parse_expression(argv[1]) != 0;
kprintf("paging is turned %s now.\n", sScreen.paging ? "on" : "off");
return 0;
}
// #pragma mark -
@@ -482,6 +557,9 @@ blue_screen_init(void)
return B_ERROR;
sModule = &gFrameBufferConsoleModule;
sScreen.paging = true;
add_debugger_command("paging", set_paging, "Enable or disable paging");
return B_OK;
}
@@ -517,6 +595,10 @@ blue_screen_getchar(void)
void
blue_screen_putchar(char c)
{
if (sScreen.ignore_output && in_command_invocation())
return;
sScreen.ignore_output = false;
hide_cursor();
parse_character(c);
@@ -528,6 +610,10 @@ blue_screen_putchar(char c)
void
blue_screen_puts(const char *text)
{
if (sScreen.ignore_output && in_command_invocation())
return;
sScreen.ignore_output = false;
hide_cursor();
while (text[0] != '\0') {
+16 -1
View File
@@ -1,6 +1,6 @@
/*
* Copyright 2008, Ingo Weinhold, [email protected]
* Copyright 2002-2007, Axel Dörfler, [email protected]
* Copyright 2002-2008, Axel Dörfler, [email protected]
* Distributed under the terms of the MIT License.
*
* Copyright 2001, Travis Geiselbrecht. All rights reserved.
@@ -27,6 +27,7 @@ static struct debugger_command *sCommands;
static jmp_buf sInvokeCommandEnv;
static bool sInvokeCommandDirectly = false;
static bool sInCommand = false;
debugger_command*
@@ -75,6 +76,15 @@ find_debugger_command(const char *name, bool partialMatch, bool& ambiguous)
}
/*! Returns wether or not a debugger command is currently being invoked.
*/
bool
in_command_invocation(void)
{
return sInCommand;
}
/*! This function is a safe gate through which debugger commands are invoked.
It sets a fault handler before invoking the command, so that an invalid
memory access will not result in another KDL session on top of this one
@@ -99,6 +109,8 @@ invoke_debugger_command(struct debugger_command *command, int argc, char** argv)
if (sInvokeCommandDirectly)
return command->func(argc, argv);
sInCommand = true;
if (setjmp(sInvokeCommandEnv) == 0) {
int result;
thread->fault_handler = (addr_t)&&error;
@@ -108,7 +120,9 @@ invoke_debugger_command(struct debugger_command *command, int argc, char** argv)
goto error;
result = command->func(argc, argv);
thread->fault_handler = oldFaultHandler;
sInCommand = false;
return result;
error:
@@ -119,6 +133,7 @@ error:
}
thread->fault_handler = oldFaultHandler;
sInCommand = false;
return 0;
}
+2
View File
@@ -24,6 +24,8 @@ debugger_command* next_debugger_command(debugger_command* command,
const char* prefix, int prefixLen);
debugger_command* find_debugger_command(const char* name, bool partialMatch,
bool& ambiguous);
bool in_command_invocation(void);
int invoke_debugger_command(struct debugger_command *command, int argc,
char** argv);