Author: dgorbachev
Date: Thu Jul 7 19:18:16 2011
New Revision: 52556
URL:
http://svn.reactos.org/svn/reactos?rev=52556&view=rev
Log:
[NTOSKRNL]
Minas Abrahamyan (minas \dot/ subs \at/ gmail \dot/ com):
- Allow to view already shown, logged debug messages on the screen (bug #6018).
Modified:
trunk/reactos/ntoskrnl/kd/kdio.c
trunk/reactos/ntoskrnl/kdbg/kdb_cli.c
Modified: trunk/reactos/ntoskrnl/kd/kdio.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/kd/kdio.c?rev=525…
==============================================================================
--- trunk/reactos/ntoskrnl/kd/kdio.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/kd/kdio.c [iso-8859-1] Thu Jul 7 19:18:16 2011
@@ -33,7 +33,15 @@
CHAR KdpScreenLineBuffer[KdpScreenLineLenght + 1] = "";
ULONG KdpScreenLineBufferPos = 0, KdpScreenLineLength = 0;
-/* DEBUG LOG FUNCTIONS *******************************************************/
+const ULONG KdpDmesgBufferSize = 128 * 1024; // 512*1024; // 5*1024*1024;
+PCHAR KdpDmesgBuffer = NULL;
+volatile ULONG KdpDmesgCurrentPosition = 0;
+volatile ULONG KdpDmesgFreeBytes = 0;
+volatile ULONG KdbDmesgTotalWritten = 0;
+KSPIN_LOCK KdpDmesgLogSpinLock;
+extern volatile BOOLEAN KdbpIsInDmesgMode;
+
+/* FILE DEBUG LOG FUNCTIONS **************************************************/
VOID
NTAPI
@@ -49,8 +57,14 @@
KeWaitForSingleObject(&KdpLoggerThreadEvent, 0, KernelMode, FALSE, NULL);
/* Bug */
+ /* Keep KdpCurrentPosition and KdpFreeBytes values in local
+ * variables to avoid their possible change from Producer part,
+ * KdpPrintToLogFile function
+ */
end = KdpCurrentPosition;
num = KdpFreeBytes;
+
+ /* Now securely calculate values, based on local variables */
beg = (end + num) % KdpBufferSize;
num = KdpBufferSize - num;
@@ -148,6 +162,7 @@
IO_STATUS_BLOCK Iosb;
HANDLE ThreadHandle;
KPRIORITY Priority;
+ SIZE_T MemSizeMBs;
if (!KdpDebugMode.File) return;
@@ -175,6 +190,8 @@
/* Display separator + ReactOS version at start of the debug log */
DPRINT1("---------------------------------------------------------------\n");
DPRINT1("ReactOS "KERNEL_VERSION_STR" (Build
"KERNEL_VERSION_BUILD_STR")\n");
+ MemSizeMBs = MmNumberOfPhysicalPages * PAGE_SIZE / 1024 / 1024;
+ DPRINT1("%u System Processor [%u MB Memory]\n", KeNumberProcessors,
MemSizeMBs);
}
else if (BootPhase == 2)
{
@@ -276,6 +293,7 @@
KdpSerialInit(PKD_DISPATCH_TABLE DispatchTable,
ULONG BootPhase)
{
+ SIZE_T MemSizeMBs;
if (!KdpDebugMode.Serial) return;
if (BootPhase == 0)
@@ -301,6 +319,8 @@
/* Display separator + ReactOS version at start of the debug log */
DPRINT1("-----------------------------------------------------\n");
DPRINT1("ReactOS "KERNEL_VERSION_STR" (Build
"KERNEL_VERSION_BUILD_STR")\n");
+ MemSizeMBs = MmNumberOfPhysicalPages * PAGE_SIZE / 1024 / 1024;
+ DPRINT1("%u System Processor [%u MB Memory]\n", KeNumberProcessors,
MemSizeMBs);
DPRINT1("Command Line: %s\n", KeLoaderBlock->LoadOptions);
DPRINT1("ARC Paths: %s %s %s %s\n",
KeLoaderBlock->ArcBootDeviceName,
KeLoaderBlock->NtHalPathName,
@@ -315,11 +335,19 @@
/* SCREEN FUNCTIONS **********************************************************/
+/*
+ * Screen debug logger function KdpScreenPrint() writes text messages into
+ * KdpDmesgBuffer, using it as a circular buffer. KdpDmesgBuffer contents could
+ * be later (re)viewed using dmesg command of kdbg. KdpScreenPrint() protects
+ * KdpDmesgBuffer from simultaneous writes by use of KdpDmesgLogSpinLock.
+ */
VOID
NTAPI
KdpScreenPrint(LPSTR Message,
ULONG Length)
{
+ ULONG beg, end, num;
+ KIRQL OldIrql;
PCHAR pch = (PCHAR) Message;
while (*pch)
@@ -354,16 +382,74 @@
KdpScreenLineBuffer[0] = '\0';
KdpScreenLineLength = KdpScreenLineBufferPos = 0;
}
-
+
++pch;
}
-
+
/* Print buffered characters */
if(KdpScreenLineBufferPos != KdpScreenLineLength)
{
HalDisplayString(KdpScreenLineBuffer + KdpScreenLineBufferPos);
KdpScreenLineBufferPos = KdpScreenLineLength;
}
+
+ /* Dmesg: store Message in the buffer to show it later */
+ if (KdbpIsInDmesgMode)
+ return;
+
+ if (KdpDmesgBuffer == NULL)
+ return;
+
+ /* Acquire the printing spinlock without waiting at raised IRQL */
+ while (TRUE)
+ {
+ /* Wait when the spinlock becomes available */
+ while (!KeTestSpinLock(&KdpDmesgLogSpinLock));
+
+ /* Spinlock was free, raise IRQL */
+ KeRaiseIrql(HIGH_LEVEL, &OldIrql);
+
+ /* Try to get the spinlock */
+ if (KeTryToAcquireSpinLockAtDpcLevel(&KdpDmesgLogSpinLock))
+ break;
+
+ /* Someone else got the spinlock, lower IRQL back */
+ KeLowerIrql(OldIrql);
+ }
+
+ /* Invariant: always_true(KdpDmesgFreeBytes == KdpDmesgBufferSize);
+ * set num to min(KdpDmesgFreeBytes, Length).
+ */
+ num = (Length < KdpDmesgFreeBytes) ? Length : KdpDmesgFreeBytes;
+ beg = KdpDmesgCurrentPosition;
+ if (num != 0)
+ {
+ end = (beg + num) % KdpDmesgBufferSize;
+ if (end > beg)
+ {
+ RtlCopyMemory(KdpDmesgBuffer + beg, Message, Length);
+ }
+ else
+ {
+ RtlCopyMemory(KdpDmesgBuffer + beg, Message, KdpDmesgBufferSize - beg);
+ RtlCopyMemory(KdpDmesgBuffer, Message + (KdpDmesgBufferSize - beg), end);
+ }
+ KdpDmesgCurrentPosition = end;
+
+ /* Counting the total bytes written */
+ KdbDmesgTotalWritten += num;
+ }
+
+ /* Release spinlock */
+ KiReleaseSpinLock(&KdpDmesgLogSpinLock);
+
+ /* Lower IRQL */
+ KeLowerIrql(OldIrql);
+
+ /* Optional step(?): find out a way to notify about buffer exhaustion,
+ * and possibly fall into kbd to use dmesg command: user will read
+ * debug messages before they will be wiped over by next writes.
+ */
}
VOID
@@ -371,6 +457,7 @@
KdpScreenInit(PKD_DISPATCH_TABLE DispatchTable,
ULONG BootPhase)
{
+ SIZE_T MemSizeMBs;
if (!KdpDebugMode.Screen) return;
if (BootPhase == 0)
@@ -381,6 +468,30 @@
/* Register as a Provider */
InsertTailList(&KdProviders, &DispatchTable->KdProvidersList);
+ }
+ else if (BootPhase == 1)
+ {
+ /* Allocate a buffer for dmesg log buffer. +1 for terminating null,
+ * see kdbp_cli.c:KdbpCmdDmesg()/2
+ */
+ KdpDmesgBuffer = ExAllocatePool(NonPagedPool, KdpDmesgBufferSize + 1);
+ RtlZeroMemory(KdpDmesgBuffer, KdpDmesgBufferSize + 1);
+ KdpDmesgFreeBytes = KdpDmesgBufferSize;
+ KdbDmesgTotalWritten = 0;
+
+ /* Initialize spinlock */
+ KeInitializeSpinLock(&KdpDmesgLogSpinLock);
+
+ /* Display separator + ReactOS version at start of the debug log */
+ DPRINT1("-----------------------------------------------------\n");
+ DPRINT1("ReactOS "KERNEL_VERSION_STR" (Build
"KERNEL_VERSION_BUILD_STR")\n");
+ MemSizeMBs = MmNumberOfPhysicalPages * PAGE_SIZE / 1024 / 1024;
+ DPRINT1("%u System Processor [%u MB Memory]\n", KeNumberProcessors,
MemSizeMBs);
+ DPRINT1("Command Line: %s\n", KeLoaderBlock->LoadOptions);
+ DPRINT1("ARC Paths: %s %s %s %s\n", KeLoaderBlock->ArcBootDeviceName,
+ KeLoaderBlock->NtHalPathName,
+ KeLoaderBlock->ArcHalDeviceName,
+ KeLoaderBlock->NtBootPathName);
}
else if (BootPhase == 2)
{
Modified: trunk/reactos/ntoskrnl/kdbg/kdb_cli.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/kdbg/kdb_cli.c?re…
==============================================================================
--- trunk/reactos/ntoskrnl/kdbg/kdb_cli.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/kdbg/kdb_cli.c [iso-8859-1] Thu Jul 7 19:18:16 2011
@@ -42,6 +42,13 @@
#define KEY_SCAN_UP 72
#define KEY_SCAN_DOWN 80
+/* Scan codes of keyboard keys: */
+#define KEYSC_END 0x004f
+#define KEYSC_PAGEUP 0x0049
+#define KEYSC_PAGEDOWN 0x0051
+#define KEYSC_HOME 0x0047
+#define KEYSC_ARROWUP 0x0048
+
#define KDB_ENTER_CONDITION_TO_STRING(cond) \
((cond) == KdbDoNotEnter ? "never" : \
((cond) == KdbEnterAlways ? "always" : \
@@ -81,6 +88,7 @@
static BOOLEAN KdbpCmdFilter(ULONG Argc, PCHAR Argv[]);
static BOOLEAN KdbpCmdSet(ULONG Argc, PCHAR Argv[]);
static BOOLEAN KdbpCmdHelp(ULONG Argc, PCHAR Argv[]);
+static BOOLEAN KdbpCmdDmesg(ULONG Argc, PCHAR Argv[]);
/* GLOBALS *******************************************************************/
@@ -100,6 +108,17 @@
PCHAR KdbInitFileBuffer = NULL; /* Buffer where KDBinit file is loaded into during
initialization */
BOOLEAN KdbpBugCheckRequested = FALSE;
+
+/* Vars for dmesg */
+/* defined here, used in ../kd/kdio.c: */
+volatile BOOLEAN KdbpIsInDmesgMode = FALSE;
+
+/* defined in ../kd/kdio.c, declare here: */
+extern const ULONG KdpDmesgBufferSize;
+extern PCHAR KdpDmesgBuffer;
+extern volatile ULONG KdpDmesgCurrentPosition;
+extern volatile ULONG KdpDmesgFreeBytes;
+extern volatile ULONG KdbDmesgTotalWritten;
static const struct
{
@@ -150,6 +169,8 @@
{ "bugcheck", "bugcheck", "Bugchecks the system.",
KdbpCmdBugCheck },
{ "filter", "filter
[error|warning|trace|info|level]+|-[componentname|default]", "Enable/disable
debug channels", KdbpCmdFilter },
{ "set", "set [var] [value]", "Sets var to value or displays
value of var.", KdbpCmdSet },
+ { "dmesg", "dmesg", "Display debug messages on screen, with
navigation on pages.", KdbpCmdDmesg },
+ { "kmsg", "kmsg", "Kernel dmesg. Alias for dmesg.",
KdbpCmdDmesg },
{ "help", "help", "Display help screen.", KdbpCmdHelp
}
};
@@ -1895,6 +1916,58 @@
return FALSE;
}
+VOID
+KdbpPager(
+ IN PCHAR Buffer,
+ IN ULONG BufLength);
+
+/*!\brief Display debug messages on screen, with paging.
+ *
+ * Keys for per-page view: Home, End, PageUp, Arrow Up, PageDown,
+ * all others are as PageDown.
+ */
+static BOOLEAN
+KdbpCmdDmesg(
+ ULONG Argc,
+ PCHAR Argv[])
+{
+ ULONG beg, end;
+
+ KdbpIsInDmesgMode = TRUE; /* Toggle logging flag */
+ if (!KdpDmesgBuffer)
+ {
+ KdbpPrint("Dmesg: error, buffer is not allocated! /DEBUGPORT=SCREEN kernel param
required for dmesg.\n");
+ return TRUE;
+ }
+
+ KdbpPrint("*** Dmesg *** TotalWritten=%lu, BufferSize=%lu,
CurrentPosition=%lu\n",
+ KdbDmesgTotalWritten, KdpDmesgBufferSize, KdpDmesgCurrentPosition);
+
+ // Pass data to the pager:
+ end = KdpDmesgCurrentPosition;
+ beg = (end + KdpDmesgFreeBytes) % KdpDmesgBufferSize;
+
+ // no roll-overs, and overwritten=lost bytes
+ if (KdbDmesgTotalWritten <= KdpDmesgBufferSize)
+ {
+ // show buffer (KdpDmesgBuffer + beg, num)
+ KdbpPager(KdpDmesgBuffer, KdpDmesgCurrentPosition);
+ }
+ else
+ {
+ // show 2 buffers: (KdpDmesgBuffer + beg, KdpDmesgBufferSize - beg)
+ // and: (KdpDmesgBuffer, end)
+ KdbpPager(KdpDmesgBuffer + beg, KdpDmesgBufferSize - beg);
+ KdbpPrint("*** Dmesg: buffer rollup ***\n");
+ KdbpPager(KdpDmesgBuffer, end);
+ }
+ KdbpPrint("*** Dmesg: end of output ***\n");
+
+ KdbpIsInDmesgMode = FALSE; /* Toggle logging flag */
+
+ return TRUE;
+}
+
/*!\brief Sets or displays a config variables value.
*/
static BOOLEAN
@@ -2110,6 +2183,7 @@
*
* \note Doesn't correctly handle \\t and terminal escape sequences when calculating
the
* number of lines required to print a single line from the Buffer in the
terminal.
+ * Prints maximum 4096 chars, because of its buffer size.
*/
VOID
KdbpPrint(
@@ -2215,12 +2289,12 @@
if (KdbNumberOfRowsTerminal <= 0)
{
/* Set number of rows to the default. */
- KdbNumberOfRowsTerminal = 24;
+ KdbNumberOfRowsTerminal = 23; //24; //Mna.: 23 for SCREEN debugport
}
else if (KdbNumberOfColsTerminal <= 0)
{
/* Set number of cols to the default. */
- KdbNumberOfColsTerminal = 80;
+ KdbNumberOfColsTerminal = 75; //80; //Mna.: 75 for SCREEN debugport
}
}
@@ -2256,6 +2330,7 @@
DbgPrint("\n");
DbgPrint("--- Press q to abort, any other key to continue ---");
+ RowsPrintedByTerminal++; /* added by Mna. */
if (KdbDebugState & KD_DEBUG_KDSERIAL)
c = KdbpGetCharSerial();
@@ -2315,6 +2390,350 @@
DbgPrint("%s", p);
+ if (c != '\0')
+ p[i + 1] = c;
+
+ /* Set p to the start of the next line and
+ * remember the number of rows/cols printed
+ */
+ p += i;
+ if (p[0] == '\n')
+ {
+ p++;
+ KdbNumberOfColsPrinted = 0;
+ }
+ else
+ {
+ ASSERT(p[0] == '\0');
+ KdbNumberOfColsPrinted += i;
+ }
+
+ KdbNumberOfRowsPrinted += RowsPrintedByTerminal;
+ }
+}
+
+/** memrchr(), explicitly defined, since was absent in MinGW of RosBE. */
+/*
+ * Reverse memchr()
+ * Find the last occurrence of 'c' in the buffer 's' of size
'n'.
+ */
+void *
+memrchr(const void *s, int c, size_t n)
+{
+ const unsigned char *cp;
+
+ if (n != 0)
+ {
+ cp = (unsigned char *)s + n;
+ do
+ {
+ if (*(--cp) == (unsigned char)c)
+ return (void *)cp;
+ } while (--n != 0);
+ }
+ return NULL;
+}
+
+/*!\brief Calculate pointer position for N lines upper of current position.
+ *
+ * \param Buffer Characters buffer to operate on.
+ * \param BufLength Buffer size.
+ *
+ * \note Calculate pointer position for N lines upper of current displaying
+ * position within the given buffer.
+ *
+ * Used by KdbpPager().
+ * Now N lines count is hardcoded to KdbNumberOfRowsTerminal.
+ */
+PCHAR
+CountOnePageUp(PCHAR Buffer, ULONG BufLength, PCHAR pCurPos)
+{
+ PCHAR p;
+ // p0 is initial guess of Page Start
+ ULONG p0len = KdbNumberOfRowsTerminal * KdbNumberOfColsTerminal;
+ PCHAR p0 = pCurPos - p0len;
+ PCHAR prev_p = p0, p1;
+ ULONG j;
+
+ if (pCurPos < Buffer)
+ pCurPos = Buffer;
+ ASSERT(pCurPos <= Buffer + BufLength);
+
+ p = memrchr(p0, '\n', p0len);
+ if (NULL == p)
+ p = p0;
+ for (j = KdbNumberOfRowsTerminal; j--; )
+ {
+ p1 = memrchr(p0, '\n', p-p0);
+ prev_p = p;
+ p = p1;
+ if (NULL == p)
+ {
+ p = prev_p;
+ if (NULL == p)
+ p = p0;
+ break;
+ }
+ int linesCnt = (KdbNumberOfColsTerminal+prev_p-p-2) / KdbNumberOfColsTerminal;
+ if (linesCnt > 1)
+ j -= linesCnt-1;
+ }
+
+ ASSERT(p != 0);
+ ++p;
+ return p;
+}
+
+/*!\brief Prints the given string with, page by page.
+ *
+ * \param Buffer Characters buffer to print.
+ * \param BufferLen Buffer size.
+ *
+ * \note Doesn't correctly handle \\t and terminal escape sequences when calculating
the
+ * number of lines required to print a single line from the Buffer in the
terminal.
+ * Maximum length of buffer is limited only by memory size.
+ *
+ * Note: BufLength should be greater then (KdbNumberOfRowsTerminal *
KdbNumberOfColsTerminal).
+ *
+ */
+VOID
+KdbpPager(
+ IN PCHAR Buffer,
+ IN ULONG BufLength)
+{
+ static CHAR InBuffer[4096];
+ static BOOLEAN TerminalInitialized = FALSE;
+ static BOOLEAN TerminalConnected = FALSE;
+ static BOOLEAN TerminalReportsSize = TRUE;
+ CHAR c = '\0';
+ PCHAR p, p2;
+ ULONG Length;
+ ULONG i, j;
+ LONG RowsPrintedByTerminal;
+ ULONG ScanCode;
+
+ if( BufLength == 0)
+ return;
+
+ /* Check if the user has aborted output of the current command */
+ if (KdbOutputAborted)
+ return;
+
+ /* Initialize the terminal */
+ if (!TerminalInitialized)
+ {
+ DbgPrint("\x1b[7h"); /* Enable linewrap */
+
+ /* Query terminal type */
+ /*DbgPrint("\x1b[Z");*/
+ DbgPrint("\x05");
+
+ TerminalInitialized = TRUE;
+ Length = 0;
+ KeStallExecutionProcessor(100000);
+
+ for (;;)
+ {
+ c = KdbpTryGetCharSerial(5000);
+ if (c == -1)
+ break;
+
+ InBuffer[Length++] = c;
+ if (Length >= (sizeof (InBuffer) - 1))
+ break;
+ }
+
+ InBuffer[Length] = '\0';
+ if (Length > 0)
+ TerminalConnected = TRUE;
+ }
+
+ /* Get number of rows and columns in terminal */
+ if ((KdbNumberOfRowsTerminal < 0) || (KdbNumberOfColsTerminal < 0) ||
+ (KdbNumberOfRowsPrinted) == 0) /* Refresh terminal size each time when number of
rows printed is 0 */
+ {
+ if ((KdbDebugState & KD_DEBUG_KDSERIAL) && TerminalConnected
&& TerminalReportsSize)
+ {
+ /* Try to query number of rows from terminal. A reply looks like
"\x1b[8;24;80t" */
+ TerminalReportsSize = FALSE;
+ KeStallExecutionProcessor(100000);
+ DbgPrint("\x1b[18t");
+ c = KdbpTryGetCharSerial(5000);
+
+ if (c == KEY_ESC)
+ {
+ c = KdbpTryGetCharSerial(5000);
+ if (c == '[')
+ {
+ Length = 0;
+
+ for (;;)
+ {
+ c = KdbpTryGetCharSerial(5000);
+ if (c == -1)
+ break;
+
+ InBuffer[Length++] = c;
+ if (isalpha(c) || Length >= (sizeof (InBuffer) - 1))
+ break;
+ }
+
+ InBuffer[Length] = '\0';
+ if (InBuffer[0] == '8' && InBuffer[1] ==
';')
+ {
+ for (i = 2; (i < Length) && (InBuffer[i] !=
';'); i++);
+
+ if (Buffer[i] == ';')
+ {
+ Buffer[i++] = '\0';
+
+ /* Number of rows is now at Buffer + 2 and number of cols at
Buffer + i */
+ KdbNumberOfRowsTerminal = strtoul(InBuffer + 2, NULL, 0);
+ KdbNumberOfColsTerminal = strtoul(InBuffer + i, NULL, 0);
+ TerminalReportsSize = TRUE;
+ }
+ }
+ }
+ /* Clear further characters */
+ while ((c = KdbpTryGetCharSerial(5000)) != -1);
+ }
+ }
+
+ if (KdbNumberOfRowsTerminal <= 0)
+ {
+ /* Set number of rows to the default. */
+ KdbNumberOfRowsTerminal = 24;
+ }
+ else if (KdbNumberOfColsTerminal <= 0)
+ {
+ /* Set number of cols to the default. */
+ KdbNumberOfColsTerminal = 80;
+ }
+ }
+
+ /* Get the string */
+ p = Buffer;
+
+ while (p[0] != '\0')
+ {
+ if ( p > Buffer+BufLength)
+ {
+ DbgPrint("Dmesg: error, p > Buffer+BufLength,d=%d", p -
(Buffer+BufLength));
+ return;
+ }
+ i = strcspn(p, "\n");
+
+ // Are we out of buffer?
+ if (p + i > Buffer + BufLength)
+ // Leaving pager function:
+ break;
+
+ /* Calculate the number of lines which will be printed in the terminal
+ * when outputting the current line
+ */
+ if (i > 0)
+ RowsPrintedByTerminal = (i + KdbNumberOfColsPrinted - 1) /
KdbNumberOfColsTerminal;
+ else
+ RowsPrintedByTerminal = 0;
+
+ if (p[i] == '\n')
+ RowsPrintedByTerminal++;
+
+ /*DbgPrint("!%d!%d!%d!%d!", KdbNumberOfRowsPrinted,
KdbNumberOfColsPrinted, i, RowsPrintedByTerminal);*/
+
+ /* Display a prompt if we printed one screen full of text */
+ if (KdbNumberOfRowsTerminal > 0 &&
+ (LONG)(KdbNumberOfRowsPrinted + RowsPrintedByTerminal) >=
KdbNumberOfRowsTerminal)
+ {
+ if (KdbNumberOfColsPrinted > 0)
+ DbgPrint("\n");
+
+ DbgPrint("--- Press q to abort, e/End,h/Home,u/PgUp, other key/PgDn
---");
+ RowsPrintedByTerminal++;
+
+ if (KdbDebugState & KD_DEBUG_KDSERIAL)
+ c = KdbpGetCharSerial();
+ else
+ c = KdbpGetCharKeyboard(&ScanCode);
+
+ if (c == '\r')
+ {
+ /* Try to read '\n' which might follow '\r' - if \n is
not received here
+ * it will be interpreted as "return" when the next command
should be read.
+ */
+ if (KdbDebugState & KD_DEBUG_KDSERIAL)
+ c = KdbpTryGetCharSerial(5);
+ else
+ c = KdbpTryGetCharKeyboard(&ScanCode, 5);
+ }
+
+ //DbgPrint("\n"); //Consize version: don't show pressed key
+ DbgPrint(" '%c'/scan=%04x\n", c, ScanCode); // Shows
pressed key
+
+ if (c == 'q')
+ {
+ KdbOutputAborted = TRUE;
+ return;
+ }
+ if ( ScanCode == KEYSC_END || c=='e')
+ {
+ PCHAR pBufEnd = Buffer + BufLength;
+ p = CountOnePageUp(Buffer, BufLength, pBufEnd);
+ i = strcspn(p, "\n");
+ }
+ else if (ScanCode == KEYSC_PAGEUP || c=='u')
+ {
+ p = CountOnePageUp(Buffer, BufLength, p);
+ i = strcspn(p, "\n");
+ }
+ else if (ScanCode == KEYSC_HOME || c=='h')
+ {
+ p = Buffer;
+ i = strcspn(p, "\n");
+ }
+ else if (ScanCode == KEYSC_ARROWUP)
+ {
+ p = CountOnePageUp(Buffer, BufLength, p);
+ i = strcspn(p, "\n");
+ }
+
+ KdbNumberOfRowsPrinted = 0;
+ KdbNumberOfColsPrinted = 0;
+ }
+
+ /* Insert a NUL after the line and print only the current line. */
+ if (p[i] == '\n' && p[i + 1] != '\0')
+ {
+ c = p[i + 1];
+ p[i + 1] = '\0';
+ }
+ else
+ {
+ c = '\0';
+ }
+
+ /* Remove escape sequences from the line if there's no terminal connected */
+ if (!TerminalConnected)
+ {
+ while ((p2 = strrchr(p, '\x1b'))) /* Look for escape character */
+ {
+ if (p2[1] == '[')
+ {
+ j = 2;
+ while (!isalpha(p2[j++]));
+ strcpy(p2, p2 + j);
+ }
+ else
+ {
+ strcpy(p2, p2 + 1);
+ }
+ }
+ }
+
+ // The main printing of the current line:
+ DbgPrint(p);
+
+ // restore not null char with saved:
if (c != '\0')
p[i + 1] = c;