From 93883d01d605030696f0b505ea0e78a3086ac3b0 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Sun, 25 Aug 2013 23:44:13 +0000 Subject: [PATCH] [SACDRV]: Last WIP pass at VTUTF8ChannelConsumeEscapeSequence. Document the last few commands, and comment the entire parser so that it makes sense (within MS's definition of making sense). The erase/clear commands need cleanup/implementation, will take a pass at those later. svn path=/trunk/; revision=59827 --- reactos/drivers/sac/driver/sacdrv.h | 157 ++++++++++++- reactos/drivers/sac/driver/vtutf8chan.c | 288 ++++++++---------------- 2 files changed, 255 insertions(+), 190 deletions(-) diff --git a/reactos/drivers/sac/driver/sacdrv.h b/reactos/drivers/sac/driver/sacdrv.h index cc9c12e3a13..2490cf1b173 100644 --- a/reactos/drivers/sac/driver/sacdrv.h +++ b/reactos/drivers/sac/driver/sacdrv.h @@ -235,8 +235,10 @@ typedef enum _SAC_ANSI_COMMANDS SacEraseScreen, SacSetCursorPosition, SacSetScrollRegion, - SacSetBackgroundColor = 21, - SacSetFontColor + SacSetColors, + SacSetBackgroundColor, + SacSetFontColor, + SacSetColorsAndAttributes } SAC_ANSI_COMMANDS; // @@ -1325,3 +1327,154 @@ ChannelHasNewIBufferData(IN PSAC_CHANNEL Channel) /* Return if there's any new data in the input buffer */ return Channel->ChannelHasNewIBufferData; } + +// +// FIXME: ANSI.H +// +// +// Source: http://en.wikipedia.org/wiki/ANSI_escape_code +// +typedef enum _VT_ANSI_ATTRIBUTES +{ + // + // Attribute modifiers (mostly supported) + // + Normal, + Bold, + Faint, + Italic, + Underline, + SlowBlink, + FastBlink, + Inverse, + Conceal, + Strikethrough, + + // + // Font selectors (not supported) + // + PrimaryFont, + AlternateFont1, + AlternateFont2, + AlternateFont3, + Alternatefont4, + AlteronateFont5, + AlteronateFont6, + AlternateFont7, + AlternatEfont8, + Alternatefont9, + + // + // Additional attributes (not supported) + // + Fraktur, + DoubleUnderline, + + // + // Attribute Un-modifiers (mostly supported) + // + BoldOff, + ItalicOff, + UnderlineOff, + BlinkOff, + Reserved, + InverseOff, + ConcealOff, + StrikethroughOff, + + // + // Standard Text Color + // + SetColorStart, + SetColorBlack = SetColorStart, + SetColorRed, + SetColorGreen, + SetColorYellow, + SetColorBlue, + SetcolorMAgent, + SetColorCyan, + SetColorWhite, + SetColorMax = SetColorWhite, + + // + // Extended Text Color (not supported) + // + SetColor256, + SeTextColorDefault, + + // + // Standard Background Color + // + SetBackColorStart, + SetBackColorBlack = SetBackColorStart, + SetBackColorRed, + SetBackColorGreen, + SetBackColorYellow, + SetBackColorBlue, + SetBackcolorMAgent, + SetBackColorCyan, + SetBackColorWhite, + SetBackColorMax = SetBackColorWhite, + + // + // Extended Background Color (not supported) + // + SetBackColor256, + SetBackColorDefault, + + // + // Extra Attributes (not supported) + // + Reserved1, + Framed, + Encircled, + Overlined, + FramedOff, + OverlinedOff, + Reserved2, + Reserved3, + Reserved4, + Reserved5 + + // + // Ideograms (not supported) + // +} VT_ANSI_ATTRIBUTES; + +// +// The following site is a good reference on VT100/ANSI escape codes +// http://www.termsys.demon.co.uk/vtansi.htm +// +#define VT_ANSI_ESCAPE L'\x1B' +#define VT_ANSI_COMMAND L'[' + +#define VT_ANSI_CURSOR_UP_CHAR L'A' +#define VT_ANSI_CURSOR_UP L"[A" + +#define VT_ANSI_CURSOR_DOWN_CHAR L'B' +#define VT_ANSI_CURSOR_DOWN L"[B" + +#define VT_ANSI_CURSOR_RIGHT_CHAR L'C' +#define VT_ANSI_CURSOR_RIGHT L"[C" + +#define VT_ANSI_CURSOR_LEFT_CHAR L'D' +#define VT_ANSI_CURSOR_LEFT L"[D" + +#define VT_ANSI_ERASE_LINE_CHAR L'K' +#define VT_ANSI_ERASE_END_LINE L"[K" +#define VT_ANSI_ERASE_START_LINE L"[1K" +#define VT_ANSI_ERASE_ENTIRE_LINE L"[2K" + +#define VT_ANSI_ERASE_SCREEN_CHAR L'J' +#define VT_ANSI_ERASE_DOWN_SCREEN L"[J" +#define VT_ANSI_ERASE_UP_SCREEN L"[1J" +#define VT_ANSI_ERASE_ENTIRE_SCREEN L"[2J" + +#define VT_ANSI_BACKTAB_CHAR L'Z' +#define VT_220_BACKTAB L"[0Z" + +#define VT_ANSI_SET_ATTRIBUTE_CHAR L'm' +#define VT_ANSI_SEPARATOR_CHAR L';' +#define VT_ANSI_HVP_CURSOR_CHAR L'f' +#define VT_ANSI_CUP_CURSOR_CHAR L'H' +#define VT_ANSI_SCROLL_CHAR L'r' diff --git a/reactos/drivers/sac/driver/vtutf8chan.c b/reactos/drivers/sac/driver/vtutf8chan.c index 11f704d941e..716a8333f90 100644 --- a/reactos/drivers/sac/driver/vtutf8chan.c +++ b/reactos/drivers/sac/driver/vtutf8chan.c @@ -15,156 +15,6 @@ CHAR IncomingUtf8ConversionBuffer[4]; WCHAR IncomingUnicodeValue; -/* FUNCTIONS *****************************************************************/ - -// -// Source: http://en.wikipedia.org/wiki/ANSI_escape_code -// -typedef enum _VT_ANSI_ATTRIBUTES -{ - // - // Attribute modifiers (mostly supported) - // - Normal, - Bold, - Faint, - Italic, - Underline, - SlowBlink, - FastBlink, - Inverse, - Conceal, - Strikethrough, - - // - // Font selectors (not supported) - // - PrimaryFont, - AlternateFont1, - AlternateFont2, - AlternateFont3, - Alternatefont4, - AlteronateFont5, - AlteronateFont6, - AlternateFont7, - AlternatEfont8, - Alternatefont9, - - // - // Additional attributes (not supported) - // - Fraktur, - DoubleUnderline, - - // - // Attribute Un-modifiers (mostly supported) - // - BoldOff, - ItalicOff, - UnderlineOff, - BlinkOff, - Reserved, - InverseOff, - ConcealOff, - StrikethroughOff, - - // - // Standard Text Color - // - SetColorStart, - SetColorBlack = SetColorStart, - SetColorRed, - SetColorGreen, - SetColorYellow, - SetColorBlue, - SetcolorMAgent, - SetColorCyan, - SetColorWhite, - SetColorMax = SetColorWhite, - - // - // Extended Text Color (not supported) - // - SetColor256, - SeTextColorDefault, - - // - // Standard Background Color - // - SetBackColorStart, - SetBackColorBlack = SetBackColorStart, - SetBackColorRed, - SetBackColorGreen, - SetBackColorYellow, - SetBackColorBlue, - SetBackcolorMAgent, - SetBackColorCyan, - SetBackColorWhite, - SetBackColorMax = SetBackColorWhite, - - // - // Extended Background Color (not supported) - // - SetBackColor256, - SetBackColorDefault, - - // - // Extra Attributes (not supported) - // - Reserved1, - Framed, - Encircled, - Overlined, - FramedOff, - OverlinedOff, - Reserved2, - Reserved3, - Reserved4, - Reserved5 - - // - // Ideograms (not supported) - // -} VT_ANSI_ATTRIBUTES; - -// -// The following site is a good reference on VT100/ANSI escape codes -// http://www.termsys.demon.co.uk/vtansi.htm -// -#define VT_ANSI_ESCAPE L'\x1B' -#define VT_ANSI_COMMAND L'[' - -#define VT_ANSI_CURSOR_UP_CHAR L'A' -#define VT_ANSI_CURSOR_UP L"[A" - -#define VT_ANSI_CURSOR_DOWN_CHAR L'B' -#define VT_ANSI_CURSOR_DOWN L"[B" - -#define VT_ANSI_CURSOR_RIGHT_CHAR L'C' -#define VT_ANSI_CURSOR_RIGHT L"[C" - -#define VT_ANSI_CURSOR_LEFT_CHAR L'D' -#define VT_ANSI_CURSOR_LEFT L"[D" - -#define VT_ANSI_ERASE_LINE_CHAR L'K' -#define VT_ANSI_ERASE_END_LINE L"[K" -#define VT_ANSI_ERASE_START_LINE L"[1K" -#define VT_ANSI_ERASE_ENTIRE_LINE L"[2K" - -#define VT_ANSI_ERASE_SCREEN_CHAR L'J' -#define VT_ANSI_ERASE_DOWN_SCREEN L"[J" -#define VT_ANSI_ERASE_UP_SCREEN L"[1J" -#define VT_ANSI_ERASE_ENTIRE_SCREEN L"[2J" - -#define VT_ANSI_BACKTAB_CHAR L'Z' -#define VT_220_BACKTAB L"[0Z" - -#define VT_ANSI_SET_ATTRIBUTE_CHAR L'm' -#define VT_ANSI_SEPARATOR_CHAR L';' -#define VT_ANSI_HVP_CURSOR_CHAR L'f' -#define VT_ANSI_CUP_CURSOR_CHAR L'H' -#define VT_ANSI_SCROLL_CHAR L'r' - SAC_STATIC_ESCAPE_STRING SacStaticEscapeStrings [] = { { VT_ANSI_CURSOR_UP, 2, SacCursorUp }, @@ -180,6 +30,16 @@ SAC_STATIC_ESCAPE_STRING SacStaticEscapeStrings [] = { VT_ANSI_ERASE_ENTIRE_SCREEN, 3, SacEraseScreen }, }; +/* FUNCTIONS *****************************************************************/ + +FORCEINLINE +VOID +VTUTF8ChannelAssertCursor(IN PSAC_CHANNEL Channel) +{ + ASSERT(Channel->CursorRow < SAC_VTUTF8_ROW_HEIGHT); + ASSERT(Channel->CursorCol < SAC_VTUTF8_COL_WIDTH); +} + BOOLEAN NTAPI VTUTF8ChannelScanForNumber(IN PWCHAR String, @@ -225,16 +85,14 @@ VTUTF8ChannelProcessAttributes( return STATUS_NOT_IMPLEMENTED; } -FORCEINLINE -VOID -VTUTF8ChannelAssertCursor(IN PSAC_CHANNEL Channel) -{ - ASSERT(Channel->CursorRow < SAC_VTUTF8_ROW_HEIGHT); - ASSERT(Channel->CursorCol < SAC_VTUTF8_COL_WIDTH); -} - // -// Not a +// This function is the guts of the sequences that SAC supports. +// +// It is written to conform to the way that Microsoft's SAC driver interprets +// the ANSI standard. If you want to extend and/or "fix" it, please use a flag +// that can be set in the Registry to enable "extended" ANSI support or etc... +// +// Hermes, I'm looking at you, buddy. // ULONG NTAPI @@ -246,12 +104,18 @@ VTUTF8ChannelConsumeEscapeSequence(IN PSAC_CHANNEL Channel, PSAC_CURSOR_DATA Cursor; ASSERT(String[0] == VT_ANSI_ESCAPE); + /* Microsoft's driver does this after the O(n) check below. Be smarter. */ + if (String[1] != VT_ANSI_COMMAND) return 0; + + /* Now that we know it's a valid command, look through the common cases */ for (i = 0; i < RTL_NUMBER_OF(SacStaticEscapeStrings); i++) { + /* Check if an optimized sequence was detected */ if (!wcsncmp(String + 1, SacStaticEscapeStrings[i].Sequence, SacStaticEscapeStrings[i].Size)) { + /* Yep, return the right action, length, and set optionals to 1 */ Action = SacStaticEscapeStrings[i].Action; Result = SacStaticEscapeStrings[i].Size + 1; Number = Number2 = Number3 = 1; @@ -259,10 +123,11 @@ VTUTF8ChannelConsumeEscapeSequence(IN PSAC_CHANNEL Channel, } } - if (String[1] != VT_ANSI_COMMAND) return 0; - + /* It's a more complex sequence, start parsing it */ Result = 0; Sequence = String + 2; + + /* First, check for the cursor sequences. This is useless due to above. */ switch (*Sequence) { case VT_ANSI_CURSOR_UP_CHAR: @@ -289,113 +154,154 @@ VTUTF8ChannelConsumeEscapeSequence(IN PSAC_CHANNEL Channel, break; } + /* This must be a sequence starting with ESC[# */ if (!VTUTF8ChannelScanForNumber(Sequence, &Number)) return 0; while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++; + /* Check if this is ESC[#m */ if (*Sequence == VT_ANSI_SET_ATTRIBUTE_CHAR) { + /* Some attribute is being set, go over the ones we support */ switch (Number) { + /* Make the font standard */ case Normal: Action = SacFontNormal; break; + /* Make the font bold */ case Bold: Action = SacFontBold; break; + /* Make the font blink */ case SlowBlink: Action = SacFontBlink; break; + /* Make the font colors inverted */ case Inverse: Action = SacFontInverse; break; + /* Make the font standard intensity */ case BoldOff: Action = SacFontBoldOff; break; + /* Turn off blinking */ case BlinkOff: Action = SacFontBlinkOff; break; + /* Turn off inverted colors */ case InverseOff: Action = SacFontInverseOff; break; + /* Something else... */ default: + + /* Is a background color being set? */ if ((Number < SetBackColorStart) || (Number > SetBackColorMax)) { + /* Nope... is it the foreground color? */ if ((Number < SetColorStart) || (Number > SetColorMax)) { + /* Nope. SAC expects no other attributes so bail out */ ASSERT(FALSE); return 0; } + /* Yep -- the number will tell us which */ Action = SacSetFontColor; } else { + /* Yep -- the number will tell us which */ Action = SacSetBackgroundColor; } break; } + /* In all cases, we're done here */ goto ProcessString; } + /* The only allowed possibility now is ESC[#;# */ if (*Sequence != VT_ANSI_SEPARATOR_CHAR) return 0; - Sequence++; if (!VTUTF8ChannelScanForNumber(Sequence, &Number2)) return 0; while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++; - if (*Sequence == VT_ANSI_SET_ATTRIBUTE_CHAR) + /* There's two valid forms accepted at this point: ESC[#;#m and ESC[#;#H */ + switch (*Sequence) { - Action = 20; - goto ProcessString; + /* This is ESC[#;#m -- used to set both colors at once */ + case VT_ANSI_SET_ATTRIBUTE_CHAR: + Action = SacSetColors; + goto ProcessString; + + /* This is ESC[#;#H -- used to set the cursor position */ + case VT_ANSI_CUP_CURSOR_CHAR: + Action = SacSetCursorPosition; + goto ProcessString; + + /* Finally, this *could* be ESC[#;#; -- we'll keep parsing */ + case VT_ANSI_SEPARATOR_CHAR: + Sequence++; + break; + + /* Abandon anything else */ + default: + return 0; } - if (*Sequence == VT_ANSI_CUP_CURSOR_CHAR) + /* The SAC seems to accept a few more possibilities if a ';' follows... */ + switch (*Sequence) { - Action = SacSetCursorPosition; - goto ProcessString; - } - - if (*Sequence != VT_ANSI_SEPARATOR_CHAR) return 0; - - Sequence++; - - if ((*Sequence == VT_ANSI_CUP_CURSOR_CHAR) || - (*Sequence == VT_ANSI_HVP_CURSOR_CHAR)) - { - Action = SacSetCursorPosition; - goto ProcessString; - } - - if (*Sequence == VT_ANSI_SCROLL_CHAR) - { - Action = SacSetScrollRegion; - goto ProcessString; + /* Both ESC[#;#;H and ESC[#;#;f are really the same command */ + case VT_ANSI_CUP_CURSOR_CHAR: + case VT_ANSI_HVP_CURSOR_CHAR: + /* It's unclear why MS doesn't allow the HVP sequence on its own */ + Action = SacSetCursorPosition; + goto ProcessString; + + /* And this is the ESC[#;#;r command to set the scroll region... */ + case VT_ANSI_SCROLL_CHAR: + /* Again, not clear why ESC[#;#r isn't supported */ + Action = SacSetScrollRegion; + goto ProcessString; + + /* Anything else must be ESC[#;#;# */ + default: + break; } + /* Get the last "#" */ if (!VTUTF8ChannelScanForNumber(Sequence, &Number3)) return 0; while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++; + /* And now the only remaining possibility is ESC[#;#;#;m */ if (*Sequence == VT_ANSI_SET_ATTRIBUTE_CHAR) { - Action = 23; + /* Which sets both color and attributes in one command */ + Action = SacSetColorsAndAttributes; goto ProcessString; } + /* No other sequences supported */ return 0; ProcessString: + /* Unless we got here from the optimized path, calculate the length */ if (!Result) Result = Sequence - String + 1; + /* Get the current cell buffer */ Cursor = (PSAC_CURSOR_DATA)Channel->OBuffer; VTUTF8ChannelAssertCursor(Channel); + + /* Handle all the supported SAC ANSI commands */ switch (Action) { case SacCursorUp: @@ -519,21 +425,26 @@ ProcessString: break; case SacEraseEndOfScreen: + ASSERT(FALSE); // todo break; case SacEraseStartOfScreen: + ASSERT(FALSE); // todo break; case SacEraseScreen: + ASSERT(FALSE); // todo break; case SacSetCursorPosition: + ASSERT(FALSE); // todo break; case SacSetScrollRegion: + ASSERT(FALSE); // todo break; - case 20: + case SacSetColors: Channel->CursorColor = Number; Channel->CursorBackColor = Number2; break; @@ -546,7 +457,7 @@ ProcessString: Channel->CursorColor = Number; break; - case 23: + case SacSetColorsAndAttributes: Channel->CursorFlags = Number; Channel->CursorColor = Number2; Channel->CursorBackColor = Number3; @@ -555,6 +466,7 @@ ProcessString: break; } + /* Return the length of the sequence */ return Result; }