123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982 |
- /*++
- Copyright (c) 2014 Minoca Corp. All Rights Reserved
- Module Name:
- term.c
- Abstract:
- This module implements common terminal support. It understands roughly the
- VT220 terminal command set, with some xterm support in there too.
- Author:
- Evan Green 24-Jul-2014
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #define RTL_API
- #include <minoca/lib/types.h>
- #include <minoca/lib/status.h>
- #include <minoca/lib/rtl.h>
- #include <minoca/lib/termlib.h>
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- /*++
- Structure Description:
- This structure stores the decoding information for a terminal escape
- sequence.
- Members:
- PreParameterString - Stores an optional pointer to the sequence of
- characters occurring before the parameter.
- PostParameterString - Stores the sequence of strings occurring after the
- parameters.
- Command - Stores the resulting command.
- --*/
- typedef struct _TERMINAL_DECODE_ENTRY {
- PSTR PreParameterString;
- PSTR PostParameterString;
- TERMINAL_COMMAND Command;
- } TERMINAL_DECODE_ENTRY, *PTERMINAL_DECODE_ENTRY;
- /*++
- Structure Description:
- This structure stores the decoding information for a terminal escape
- sequence.
- Members:
- Sequence - Supplies a pointer to a string containing the escape sequence
- (after the escape) corresponding to this key.
- ApplicationMode - Supplies a boolean indicating if this key represents
- application mode keys or normal mode keys.
- Key - Supplies the corresponding key code for this sequence.
- --*/
- typedef struct _TERMINAL_KEY_ENTRY {
- PSTR Sequence;
- BOOL ApplicationMode;
- TERMINAL_KEY Key;
- } TERMINAL_KEY_ENTRY, *PTERMINAL_KEY_ENTRY;
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- BOOL
- TermpMatchCommand (
- PSTR PreString,
- UINTN PreStringSize,
- PSTR PostString,
- UINTN PostStringSize,
- PTERMINAL_DECODE_ENTRY DecodeEntry,
- PBOOL PartialMatch
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- TERMINAL_DECODE_ENTRY TermCommandTable[] = {
- {"[", "A", TerminalCommandCursorUp},
- {"[", "B", TerminalCommandCursorDown},
- {"[", "C", TerminalCommandCursorRight},
- {"[", "D", TerminalCommandCursorLeft},
- {"[", "f", TerminalCommandCursorMove},
- {"[", "H", TerminalCommandCursorMove},
- {"[", "d", TerminalCommandSetCursorRowAbsolute},
- {"[", "e", TerminalCommandCursorDown},
- {"[", "G", TerminalCommandSetCursorColumnAbsolute},
- {"", "c", TerminalCommandReset},
- {"", "D", TerminalCommandCursorDown},
- {"", "E", TerminalCommandNextLine},
- {"", "M", TerminalCommandReverseLineFeed},
- {"", "7", TerminalCommandSaveCursorAndAttributes},
- {"", "8", TerminalCommandRestoreCursorAndAttributes},
- {"", "H", TerminalCommandSetHorizontalTab},
- {"[", "g", TerminalCommandClearHorizontalTab},
- {"[", "r", TerminalCommandSetTopAndBottomMargin},
- {"[", "J", TerminalCommandEraseInDisplay},
- {"[?", "J", TerminalCommandEraseInDisplaySelective},
- {"[", "K", TerminalCommandEraseInLine},
- {"[?", "K", TerminalCommandEraseInLineSelective},
- {"[", "L", TerminalCommandInsertLines},
- {"[", "M", TerminalCommandDeleteLines},
- {"[", "@", TerminalCommandInsertCharacters},
- {"[", "P", TerminalCommandDeleteCharacters},
- {"[", "X", TerminalCommandEraseCharacters},
- {"", ">", TerminalCommandKeypadNumeric},
- {"", "=", TerminalCommandKeypadApplication},
- {"[", "l", TerminalCommandClearMode},
- {"[", "h", TerminalCommandSetMode},
- {"[?", "l", TerminalCommandClearPrivateMode},
- {"[?", "h", TerminalCommandSetPrivateMode},
- {"(", "", TerminalCommandSelectG0CharacterSet},
- {")", "", TerminalCommandSelectG1CharacterSet},
- {"*", "", TerminalCommandSelectG2CharacterSet},
- {"+", "", TerminalCommandSelectG3CharacterSet},
- {"[", "m", TerminalCommandSelectGraphicRendition},
- {"", "c", TerminalCommandReset},
- {"[", "!p", TerminalCommandSoftReset},
- {"[", "c", TerminalCommandDeviceAttributesPrimary},
- {"[", ">c", TerminalCommandDeviceAttributesSecondary},
- {"[", "S", TerminalCommandScrollUp},
- {"[", "T", TerminalCommandScrollDown},
- {"#", "3", TerminalCommandDoubleLineHeightTopHalf},
- {"#", "4", TerminalCommandDoubleLineHeightBottomHalf},
- {"#", "5", TerminalCommandSingleWidthLine},
- {"#", "6", TerminalCommandDoubleWidthLine},
- };
- TERMINAL_KEY_ENTRY TermKeyTable[] = {
- {"[A", FALSE, TerminalKeyUp},
- {"[B", FALSE, TerminalKeyDown},
- {"[C", FALSE, TerminalKeyRight},
- {"[D", FALSE, TerminalKeyLeft},
- {"[2~", FALSE, TerminalKeyInsert},
- {"[3~", FALSE, TerminalKeyDelete},
- {"[1~", FALSE, TerminalKeyHome},
- {"[4~", FALSE, TerminalKeyEnd},
- {"[5~", FALSE, TerminalKeyPageUp},
- {"[6~", FALSE, TerminalKeyPageDown},
- };
- //
- // ------------------------------------------------------------------ Functions
- //
- TERMINAL_PARSE_RESULT
- TermProcessOutput (
- PTERMINAL_COMMAND_DATA Command,
- CHAR Character
- )
- /*++
- Routine Description:
- This routine processes a character destined for the terminal output.
- Arguments:
- Command - Supplies a pointer to the current command state. If this is the
- first character ever, zero out the command before calling this function.
- Character - Supplies the input character.
- Return Value:
- Returns a terminal output result code indicating if the character is just a
- normal display character, part of a command, or the last character in a
- complete command.
- --*/
- {
- UINTN CommandCount;
- UINTN CommandIndex;
- PTERMINAL_DECODE_ENTRY DecodeEntry;
- BOOL Match;
- UINTN ParameterIndex;
- BOOL PartialMatch;
- //
- // An escape character always starts a new command.
- //
- if (Character == TERMINAL_ESCAPE) {
- Command->Flags = TERMINAL_COMMAND_SEEN_ESCAPE;
- Command->CommandCharacterCount = 0;
- Command->ParameterCount = 0;
- Command->ParameterIndex = 0;
- Command->Parameter[0] = 0;
- Command->PreParameterSize = 0;
- Command->PostParameterSize = 0;
- Command->Command = TerminalCommandInvalid;
- return TerminalParseResultPartialCommand;
- }
- //
- // If an escape hasn't been seen then this is just an ordinary character.
- //
- if ((Command->Flags & TERMINAL_COMMAND_SEEN_ESCAPE) == 0) {
- return TerminalParseResultNormalCharacter;
- }
- //
- // If it's a control character, return it as normal.
- //
- if ((Character < ' ') || (Character > 0x7F)) {
- return TerminalParseResultNormalCharacter;
- }
- //
- // If this is a digit, then it's either a parameter for a CSI (^[) sequence
- // or it's a command of its own (like ^7 or ^8). If a CSI has been seen,
- // treat it as a parameter, otherwise, treat it like a command character.
- //
- if ((Character >= '0') && (Character <= '9')) {
- if ((Command->PreParameterSize != 0) &&
- (Command->PreParameter[0] == TERMINAL_INTRODUCER)) {
- Command->Flags |= TERMINAL_COMMAND_SEEN_PARAMETER;
- ParameterIndex = Command->ParameterIndex;
- //
- // If this is the first time a digit for a parameter is specified,
- // then bump up the parameter count. Watch out for too many
- // parameters.
- //
- if (Command->ParameterCount < ParameterIndex + 1) {
- if (ParameterIndex >= TERMINAL_MAX_PARAMETERS) {
- Command->Flags = 0;
- return TerminalParseResultNormalCharacter;
- }
- Command->ParameterCount = ParameterIndex + 1;
- Command->Parameter[ParameterIndex] = 0;
- }
- Command->Parameter[ParameterIndex] *= 10;
- Command->Parameter[ParameterIndex] += Character - '0';
- return TerminalParseResultPartialCommand;
- }
- //
- // Move to the next parameter slot.
- //
- } else if (Character == TERMINAL_PARAMETER_SEPARATOR) {
- Command->ParameterIndex += 1;
- if (Command->ParameterIndex < TERMINAL_MAX_PARAMETERS) {
- Command->Parameter[Command->ParameterIndex] = 0;
- }
- return TerminalParseResultPartialCommand;
- }
- //
- // If the character was not a parameter, then add it to the command buffer.
- // Add it to the beginning or end depending on whether or not a parameter
- // was seen.
- //
- if ((Command->Flags & TERMINAL_COMMAND_SEEN_PARAMETER) != 0) {
- if (Command->PostParameterSize >= TERMINAL_MAX_COMMAND_CHARACTERS) {
- Command->Flags = 0;
- return TerminalParseResultNormalCharacter;
- }
- Command->PostParameter[Command->PostParameterSize] = Character;
- Command->PostParameterSize += 1;
- } else {
- if (Command->PreParameterSize >= TERMINAL_MAX_COMMAND_CHARACTERS) {
- Command->Flags = 0;
- return TerminalParseResultNormalCharacter;
- }
- Command->PreParameter[Command->PreParameterSize] = Character;
- Command->PreParameterSize += 1;
- }
- //
- // As a shortcut to prevent the following loop in common cases, skip the
- // test if this is the introducer.
- //
- if (Character == TERMINAL_INTRODUCER) {
- return TerminalParseResultPartialCommand;
- }
- //
- // Look to see if the command matches anything completely or partially.
- //
- PartialMatch = FALSE;
- CommandCount = sizeof(TermCommandTable) / sizeof(TermCommandTable[0]);
- for (CommandIndex = 0; CommandIndex < CommandCount; CommandIndex += 1) {
- DecodeEntry = &(TermCommandTable[CommandIndex]);
- Match = TermpMatchCommand(Command->PreParameter,
- Command->PreParameterSize,
- Command->PostParameter,
- Command->PostParameterSize,
- DecodeEntry,
- &PartialMatch);
- if (Match != FALSE) {
- break;
- }
- //
- // If there is no post parameter and the decode entry's pre-parameter
- // string is empty, try matching the pre-parameter string against the
- // post-parameter decode entry string.
- //
- if ((DecodeEntry->PreParameterString[0] == '\0') &&
- (Command->PostParameterSize == 0)) {
- Match = TermpMatchCommand(NULL,
- 0,
- Command->PreParameter,
- Command->PreParameterSize,
- DecodeEntry,
- &PartialMatch);
- if (Match != FALSE) {
- break;
- }
- }
- }
- //
- // If the loop made it to the end, then no command matched exactly.
- //
- if (CommandIndex == CommandCount) {
- if (PartialMatch != FALSE) {
- return TerminalParseResultPartialCommand;
- }
- Command->Flags = 0;
- return TerminalParseResultNormalCharacter;
- }
- Command->Command = DecodeEntry->Command;
- Command->Flags = 0;
- return TerminalParseResultCompleteCommand;
- }
- VOID
- TermNormalizeParameters (
- PTERMINAL_COMMAND_DATA Command
- )
- /*++
- Routine Description:
- This routine normalizes the command parameters to their expected defaults
- and allowed.
- Arguments:
- Command - Supplies a pointer to the complete command.
- Return Value:
- None.
- --*/
- {
- UINTN Index;
- switch (Command->Command) {
- case TerminalCommandCursorUp:
- case TerminalCommandCursorDown:
- case TerminalCommandCursorLeft:
- case TerminalCommandCursorRight:
- case TerminalCommandScrollUp:
- case TerminalCommandScrollDown:
- case TerminalCommandSetCursorRowAbsolute:
- case TerminalCommandSetCursorColumnAbsolute:
- if (Command->ParameterCount == 0) {
- Command->Parameter[0] = 1;
- }
- Command->ParameterCount = 1;
- if (Command->Parameter[0] == 0) {
- Command->Parameter[0] = 1;
- }
- break;
- case TerminalCommandCursorMove:
- for (Index = 0; Index < 2; Index += 1) {
- if (Index >= Command->ParameterCount) {
- Command->Parameter[Index] = 1;
- } else if (Command->Parameter[Index] == 0) {
- Command->Parameter[Index] = 1;
- }
- }
- Command->ParameterCount = 2;
- break;
- case TerminalCommandNextLine:
- case TerminalCommandReverseLineFeed:
- case TerminalCommandSaveCursorAndAttributes:
- case TerminalCommandRestoreCursorAndAttributes:
- case TerminalCommandSetHorizontalTab:
- case TerminalCommandKeypadNumeric:
- case TerminalCommandKeypadApplication:
- case TerminalCommandReset:
- case TerminalCommandSoftReset:
- case TerminalCommandDeviceAttributesPrimary:
- case TerminalCommandDeviceAttributesSecondary:
- case TerminalCommandDoubleLineHeightTopHalf:
- case TerminalCommandDoubleLineHeightBottomHalf:
- case TerminalCommandSingleWidthLine:
- case TerminalCommandDoubleWidthLine:
- Command->ParameterCount = 0;
- break;
- case TerminalCommandClearHorizontalTab:
- case TerminalCommandEraseInDisplay:
- case TerminalCommandEraseInLine:
- if (Command->ParameterCount == 0) {
- Command->Parameter[0] = 0;
- }
- Command->ParameterCount = 1;
- break;
- case TerminalCommandInsertLines:
- case TerminalCommandDeleteLines:
- case TerminalCommandInsertCharacters:
- case TerminalCommandDeleteCharacters:
- case TerminalCommandEraseCharacters:
- if (Command->ParameterCount == 0) {
- Command->Parameter[0] = 1;
- }
- Command->ParameterCount = 1;
- break;
- case TerminalCommandSetTopAndBottomMargin:
- case TerminalCommandSetMode:
- case TerminalCommandClearMode:
- case TerminalCommandSelectG0CharacterSet:
- case TerminalCommandSelectG1CharacterSet:
- case TerminalCommandSelectG2CharacterSet:
- case TerminalCommandSelectG3CharacterSet:
- case TerminalCommandSelectGraphicRendition:
- default:
- break;
- }
- return;
- }
- BOOL
- TermCreateOutputSequence (
- PTERMINAL_COMMAND_DATA Command,
- PSTR Buffer,
- UINTN BufferSize
- )
- /*++
- Routine Description:
- This routine creates a terminal command sequence for a given command.
- Arguments:
- Command - Supplies a pointer to the complete command.
- Buffer - Supplies a pointer where the null-terminated command sequence will
- be returned.
- BufferSize - Supplies the size of the supplied buffer in bytes.
- Return Value:
- TRUE on success.
- FALSE on failure.
- --*/
- {
- PTERMINAL_DECODE_ENTRY DecodeEntry;
- UINTN EntryCount;
- UINTN EntryIndex;
- UINTN FinalLength;
- PSTR Format;
- UINTN ParameterIndex;
- DecodeEntry = NULL;
- EntryCount = sizeof(TermCommandTable) / sizeof(TermCommandTable[0]);
- for (EntryIndex = 0; EntryIndex < EntryCount; EntryIndex += 1) {
- DecodeEntry = &(TermCommandTable[EntryIndex]);
- if (DecodeEntry->Command == Command->Command) {
- break;
- }
- }
- if (EntryIndex == EntryCount) {
- return FALSE;
- }
- //
- // If the post parameter string is NULL, then the final sequence is a
- // single character.
- //
- if (DecodeEntry->PostParameterString[0] == '\0') {
- ASSERT(Command->PostParameterSize == 1);
- FinalLength = RtlPrintToString(Buffer,
- BufferSize,
- CharacterEncodingAscii,
- "%c%s%c",
- TERMINAL_ESCAPE,
- DecodeEntry->PreParameterString,
- Command->PostParameter[0]);
- if (FinalLength > BufferSize) {
- return FALSE;
- }
- //
- // Output the format ^<prestring><parameters><poststring>, where ^ is the
- // escape character (0x1B), and parameters are a sequence of
- // <number>;...;<number>.
- //
- } else {
- FinalLength = RtlPrintToString(Buffer,
- BufferSize,
- CharacterEncodingAscii,
- "%c%s",
- TERMINAL_ESCAPE,
- DecodeEntry->PreParameterString);
- if (FinalLength >= BufferSize) {
- return FALSE;
- }
- Buffer += FinalLength - 1;
- BufferSize -= FinalLength - 1;
- for (ParameterIndex = 0;
- ParameterIndex < Command->ParameterCount;
- ParameterIndex += 1) {
- if (ParameterIndex == Command->ParameterCount - 1) {
- Format = "%d";
- } else {
- Format = "%d;";
- }
- FinalLength = RtlPrintToString(Buffer,
- BufferSize,
- CharacterEncodingAscii,
- Format,
- Command->Parameter[ParameterIndex]);
- if (FinalLength >= BufferSize) {
- return FALSE;
- }
- Buffer += FinalLength - 1;
- BufferSize -= FinalLength - 1;
- }
- RtlPrintToString(Buffer,
- BufferSize,
- CharacterEncodingAscii,
- "%s",
- DecodeEntry->PostParameterString);
- }
- return TRUE;
- }
- TERMINAL_PARSE_RESULT
- TermProcessInput (
- PTERMINAL_KEY_DATA KeyData,
- CHAR Character
- )
- /*++
- Routine Description:
- This routine processes a character destined for the terminal input.
- Arguments:
- KeyData - Supplies a pointer to the key parsing state. If this is the first
- time calling this function, zero out this structure.
- Character - Supplies the input character.
- Return Value:
- Returns a terminal parse result code indicating if the character is just a
- normal input character, part of a command, or the last character in a
- complete command.
- --*/
- {
- UINTN CharacterIndex;
- UINTN DecodeCount;
- PTERMINAL_KEY_ENTRY DecodeEntry;
- UINTN DecodeIndex;
- BOOL PartialMatch;
- //
- // An escape character always starts a new command.
- //
- if (Character == TERMINAL_ESCAPE) {
- //
- // Two escapes in a row means ALT was held down here.
- //
- if ((KeyData->Buffer[0] == TERMINAL_ESCAPE) &&
- (KeyData->BufferSize == 1)) {
- KeyData->Flags |= TERMINAL_KEY_FLAG_ALT;
- return TerminalParseResultPartialCommand;
- }
- KeyData->Buffer[0] = Character;
- KeyData->BufferSize = 1;
- KeyData->Flags = 0;
- return TerminalParseResultPartialCommand;
- }
- if (KeyData->BufferSize == 0) {
- return TerminalParseResultNormalCharacter;
- }
- if (KeyData->BufferSize == TERMINAL_MAX_KEY_CHARACTERS) {
- ASSERT(FALSE);
- KeyData->BufferSize = 0;
- return TerminalParseResultNormalCharacter;
- }
- KeyData->Buffer[KeyData->BufferSize] = Character;
- KeyData->BufferSize += 1;
- PartialMatch = FALSE;
- DecodeCount = sizeof(TermKeyTable) / sizeof(TermKeyTable[0]);
- for (DecodeIndex = 0; DecodeIndex < DecodeCount; DecodeIndex += 1) {
- DecodeEntry = &(TermKeyTable[DecodeIndex]);
- for (CharacterIndex = 0;
- CharacterIndex < KeyData->BufferSize - 1;
- CharacterIndex += 1) {
- if (DecodeEntry->Sequence[CharacterIndex] == '\0') {
- break;
- }
- if (DecodeEntry->Sequence[CharacterIndex] !=
- KeyData->Buffer[CharacterIndex + 1]) {
- break;
- }
- }
- //
- // If not all the input characters were processed, this doesn't match.
- //
- if (CharacterIndex != KeyData->BufferSize - 1) {
- continue;
- }
- //
- // If everything matched but the sequence isn't finished, this is a
- // partial match.
- //
- if (DecodeEntry->Sequence[CharacterIndex] != '\0') {
- PartialMatch = TRUE;
- continue;
- }
- //
- // Everything matches, this is the key.
- //
- break;
- }
- if (DecodeIndex == DecodeCount) {
- if (PartialMatch != FALSE) {
- return TerminalParseResultPartialCommand;
- }
- KeyData->BufferSize = 0;
- return TerminalParseResultNormalCharacter;
- }
- KeyData->Key = DecodeEntry->Key;
- KeyData->BufferSize = 0;
- return TerminalParseResultCompleteCommand;
- }
- BOOL
- TermCreateInputSequence (
- PTERMINAL_KEY_DATA KeyData,
- PSTR Buffer,
- UINTN BufferSize
- )
- /*++
- Routine Description:
- This routine creates a terminal keyboard sequence for a given key.
- Arguments:
- KeyData - Supplies the complete key data.
- Buffer - Supplies a pointer where the null-terminated control sequence will
- be returned.
- BufferSize - Supplies the size of the supplied buffer in bytes.
- Return Value:
- TRUE on success.
- FALSE on failure.
- --*/
- {
- UINTN DecodeCount;
- PTERMINAL_KEY_ENTRY DecodeEntry;
- UINTN DecodeIndex;
- DecodeCount = sizeof(TermKeyTable) / sizeof(TermKeyTable[0]);
- for (DecodeIndex = 0; DecodeIndex < DecodeCount; DecodeIndex += 1) {
- DecodeEntry = &(TermKeyTable[DecodeIndex]);
- if (DecodeEntry->Key == KeyData->Key) {
- break;
- }
- }
- if (DecodeIndex == DecodeCount) {
- return FALSE;
- }
- if (BufferSize == 0) {
- return FALSE;
- }
- //
- // Stick an extra escape on the front if the ALT flag is set.
- //
- if ((KeyData->Flags & TERMINAL_KEY_FLAG_ALT) != 0) {
- *Buffer = TERMINAL_ESCAPE;
- Buffer += 1;
- BufferSize -= 1;
- }
- if (BufferSize == 0) {
- return FALSE;
- }
- *Buffer = TERMINAL_ESCAPE;
- Buffer += 1;
- BufferSize -= 1;
- RtlStringCopy(Buffer, DecodeEntry->Sequence, BufferSize);
- return TRUE;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- BOOL
- TermpMatchCommand (
- PSTR PreString,
- UINTN PreStringSize,
- PSTR PostString,
- UINTN PostStringSize,
- PTERMINAL_DECODE_ENTRY DecodeEntry,
- PBOOL PartialMatch
- )
- /*++
- Routine Description:
- This routine attempts to match the current input characters with the given
- command.
- Arguments:
- PreString - Supplies a pointer to the pre-parameter characters seen so far.
- PreStringSize - Supplies the size of the pre-parameter string in bytes.
- PostString - Supplies a pointer to the post-parameter characters seen so
- far.
- PostStringSize - Supplies the size of the post parameter string in bytes.
- DecodeEntry - Supplies a pointer to the decode entry to match against.
- PartialMatch - Supplies a pointer that is left alone if the entry matches
- or does not match, and is set to TRUE if the entry partially matches
- but needs more characters to fully match.
- Return Value:
- TRUE if the input matches the decode entry fully.
- FALSE if the input does not match or only partially matches the decode
- entry.
- --*/
- {
- PSTR PreStringTail;
- UINTN PreStringTailSize;
- UINTN StringIndex;
- //
- // Match the pre-parameter string.
- //
- for (StringIndex = 0; StringIndex < PreStringSize; StringIndex += 1) {
- if ((DecodeEntry->PreParameterString[StringIndex] == '\0') ||
- (DecodeEntry->PreParameterString[StringIndex] !=
- PreString[StringIndex])) {
- break;
- }
- }
- if (StringIndex != PreStringSize) {
- //
- // In the case where there were no parameters, the final character
- // may have been glommed on to the pre-parameter string. Try to
- // match the rest of the string with the post parameter string.
- //
- if ((DecodeEntry->PreParameterString[StringIndex] == 0) &&
- (PostStringSize == 0)) {
- //
- // If the post parameter string is empty, then any character
- // matches. The "Select Character Set" commands have a form like
- // this: ^({final}, where {final} is the desired hard character set.
- //
- if (DecodeEntry->PostParameterString[0] == '\0') {
- return TRUE;
- }
- PreStringTail = PreString + StringIndex;
- PreStringTailSize = PreStringSize - StringIndex;
- for (StringIndex = 0;
- StringIndex < PreStringTailSize;
- StringIndex += 1) {
- if ((DecodeEntry->PostParameterString[StringIndex] ==
- '\0') ||
- (DecodeEntry->PostParameterString[StringIndex] !=
- PreStringTail[StringIndex])) {
- break;
- }
- }
- if (StringIndex == PreStringTailSize) {
- return TRUE;
- }
- }
- return FALSE;
- }
- if (DecodeEntry->PreParameterString[StringIndex] != '\0') {
- *PartialMatch = TRUE;
- return FALSE;
- }
- //
- // If the post-parameter string is empty, return a partial match. The next
- // character (which should get glommed on to the pre-parameter string)
- // will make it complete.
- //
- if (DecodeEntry->PostParameterString[0] == '\0') {
- *PartialMatch = TRUE;
- return FALSE;
- }
- //
- // Match the post-parameter string.
- //
- for (StringIndex = 0; StringIndex < PostStringSize; StringIndex += 1) {
- if ((DecodeEntry->PostParameterString[StringIndex] == '\0') ||
- (DecodeEntry->PostParameterString[StringIndex] !=
- PostString[StringIndex])) {
- break;
- }
- }
- if (StringIndex != PostStringSize) {
- return FALSE;
- }
- if (DecodeEntry->PostParameterString[StringIndex] != '\0') {
- *PartialMatch = TRUE;
- return FALSE;
- }
- return TRUE;
- }
|