Author: ion Date: Sun Aug 25 21:56:20 2013 New Revision: 59824
URL: http://svn.reactos.org/svn/reactos?rev=59824&view=rev Log: [SACDRV]: Implement VTUTF8ChannelScanForNumber. [SACDRV]: Implement VTUTF8ChannelOEcho. [SACDRV]: WIP-lement VTUTF8ChannelConsumeEscapeSequence. Have to do some reading up on ANSI to get this right.
Modified: trunk/reactos/drivers/sac/driver/sacdrv.h trunk/reactos/drivers/sac/driver/vtutf8chan.c
Modified: trunk/reactos/drivers/sac/driver/sacdrv.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/sac/driver/sacdrv.h... ============================================================================== --- trunk/reactos/drivers/sac/driver/sacdrv.h [iso-8859-1] (original) +++ trunk/reactos/drivers/sac/driver/sacdrv.h [iso-8859-1] Sun Aug 25 21:56:20 2013 @@ -158,6 +158,8 @@ #define SAC_MAX_MESSAGES 200 #define SAC_VTUTF8_COL_WIDTH 80 #define SAC_VTUTF8_COL_HEIGHT 25 +#define SAC_VTUTF8_ROW_HEIGHT 24 +#define MAX_UTF8_ENCODE_BLOCK_LENGTH (Utf8ConversionBufferSize / 3 - 1)
// // Channel flags @@ -1012,6 +1014,17 @@ OUT PVOID *ActualWaitObject );
+BOOLEAN +NTAPI +SacTranslateUnicodeToUtf8( + IN PWCHAR SourceBuffer, + IN ULONG SourceBufferLength, + OUT PCHAR DestinationBuffer, + IN ULONG DestinationBufferSize, + OUT PULONG UTF8Count, + OUT PULONG ProcessedCount +); + // // SAC Command Functions //
Modified: trunk/reactos/drivers/sac/driver/vtutf8chan.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/sac/driver/vtutf8ch... ============================================================================== --- trunk/reactos/drivers/sac/driver/vtutf8chan.c [iso-8859-1] (original) +++ trunk/reactos/drivers/sac/driver/vtutf8chan.c [iso-8859-1] Sun Aug 25 21:56:20 2013 @@ -27,101 +27,52 @@
C_ASSERT(sizeof(SAC_CURSOR_DATA) == 6);
+typedef struct _SAC_STATIC_ESCAPE_STRING +{ + WCHAR Sequence[10]; + ULONG Size; + ULONG Action; +} SAC_STATIC_ESCAPE_STRING, *PSAC_STATIC_ESCAPE_STRING; + +SAC_STATIC_ESCAPE_STRING SacStaticEscapeStrings [] = +{ + { L"[A", 2, 0 }, + { L"[B", 2, 1 }, + { L"[C", 2, 2 }, + { L"[D", 2, 3 }, + { L"[0Z", 3, 11 }, + { L"[K", 2, 12 }, + { L"[1K", 3, 13 }, + { L"[2K", 3, 14 }, + { L"[J", 2, 15 }, + { L"[1J", 3, 16 }, + { L"[2J", 3, 17 }, +}; + #define SAC_VTUTF8_OBUFFER_SIZE 0x2D00 #define SAC_VTUTF8_IBUFFER_SIZE 0x2000
-NTSTATUS -NTAPI -VTUTF8ChannelOInit(IN PSAC_CHANNEL Channel) -{ - PSAC_CURSOR_DATA Cursor; - ULONG x, y; - CHECK_PARAMETER(Channel); - - /* Set the current channel cursor parameters */ - Channel->CursorVisible = 0; - Channel->CursorX = 40; - Channel->CursorY = 37; - - /* Loop the output buffer height by width */ - Cursor = (PSAC_CURSOR_DATA)Channel->OBuffer; - y = SAC_VTUTF8_COL_HEIGHT - 1; - do - { - x = SAC_VTUTF8_COL_WIDTH; - do - { - /* For every character, set the defaults */ - Cursor->CursorValue = ' '; - Cursor->CursorX = 40; - Cursor->CursorY = 38; - - /* Move to the next character */ - Cursor++; - } while (--x); - } while (--y); +BOOLEAN +NTAPI +VTUTF8ChannelScanForNumber(IN PWCHAR String, + OUT PULONG Number) +{ + /* If the first character is invalid, fail early */ + if ((*String < L'0') || (*String > L'9')) return FALSE; + + /* Otherwise, initialize the output and loop the string */ + *Number = 0; + while ((*String >= L'0') && (*String <= L'9')) + { + /* Save the first decimal */ + *Number = 10 * *Number; + + /* Compute and add the second one */ + *Number += *++String - L'0'; + }
/* All done */ - return STATUS_SUCCESS; -} - -NTSTATUS -NTAPI -VTUTF8ChannelCreate(IN PSAC_CHANNEL Channel) -{ - NTSTATUS Status; - CHECK_PARAMETER(Channel); - - /* Allocate the output buffer */ - Channel->OBuffer = SacAllocatePool(SAC_VTUTF8_OBUFFER_SIZE, GLOBAL_BLOCK_TAG); - CHECK_ALLOCATION(Channel->OBuffer); - - /* Allocate the input buffer */ - Channel->IBuffer = SacAllocatePool(SAC_VTUTF8_IBUFFER_SIZE, GLOBAL_BLOCK_TAG); - CHECK_ALLOCATION(Channel->IBuffer); - - /* Initialize the output stream */ - Status = VTUTF8ChannelOInit(Channel); - if (NT_SUCCESS(Status)) return Status; - - /* Reset all flags and return success */ - _InterlockedExchange(&Channel->ChannelHasNewOBufferData, 0); - _InterlockedExchange(&Channel->ChannelHasNewIBufferData, 0); - return STATUS_SUCCESS; -} - -NTSTATUS -NTAPI -VTUTF8ChannelDestroy(IN PSAC_CHANNEL Channel) -{ - CHECK_PARAMETER(Channel); - - /* Free the buffer and then destroy the channel */ - if (Channel->OBuffer) SacFreePool(Channel->OBuffer); - if (Channel->IBuffer) SacFreePool(Channel->IBuffer); - return ChannelDestroy(Channel); -} - -NTSTATUS -NTAPI -VTUTF8ChannelORead( - IN PSAC_CHANNEL Channel, - IN PCHAR Buffer, - IN ULONG BufferSize, - OUT PULONG ByteCount - ) -{ - return STATUS_NOT_IMPLEMENTED; -} - -BOOLEAN -NTAPI -VTUTF8ChannelScanForNumber( - IN PWCHAR String, - OUT PULONG Number - ) -{ - return FALSE; + return TRUE; }
NTSTATUS @@ -146,14 +97,408 @@ return STATUS_NOT_IMPLEMENTED; }
-NTSTATUS -NTAPI -VTUTF8ChannelConsumeEscapeSequence( - IN PSAC_CHANNEL Channel, - IN PWCHAR String - ) -{ - 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); +} + +ULONG +NTAPI +VTUTF8ChannelConsumeEscapeSequence(IN PSAC_CHANNEL Channel, + IN PWCHAR String) +{ + ULONG Number, Number2, Number3, i, Action, Result; + PWCHAR Sequence; + PSAC_CURSOR_DATA Cursor; + ASSERT(String[0] == L'\x1B'); + + for (i = 0; i < RTL_NUMBER_OF(SacStaticEscapeStrings); i++) + { + if (!wcsncmp(String + 1, + SacStaticEscapeStrings[i].Sequence, + SacStaticEscapeStrings[i].Size)) + { + Action = SacStaticEscapeStrings[i].Action; + Result = SacStaticEscapeStrings[i].Size + 1; + Number = Number2 = Number3 = 1; + goto ProcessString; + } + } + + if (String[1] != L'[') return 0; + + Sequence = String + 2; + switch (*Sequence) + { + case L'A': + Action = 0; + break; + case L'B': + Action = 1; + break; + case L'C': + Action = 3; //bug + break; + case L'D': + Action = 2; //bug + break; + case L'K': + Action = 12; + break; + default: + if (!VTUTF8ChannelScanForNumber(Sequence, &Number)) return 0; + + while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++; + + if (*Sequence == 'm') + { + switch (Number) + { + case 0: + Action = 4; + break; + case 1: + Action = 7; + break; + + case 5: + Action = 5; + break; + + case 7: + Action = 9; + break; + + case 22: + Action = 8; + break; + + case 25: + Action = 6; + break; + + case 27: + Action = 10; + break; + + default: + if ((Number < 40) || (Number > 47)) + { + if ((Number < 30) || (Number > 39)) + { + ASSERT(FALSE); + return 0; + } + + Action = 22; + } + else + { + Action = 21; + } + } + } + else + { + if (*Sequence != L';') return 0; + Sequence++; + + if (!VTUTF8ChannelScanForNumber(Sequence, &Number2)) return 0; + + while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++; + + if (*Sequence == L'm') + { + Action = 20; + } + else + { + if (*Sequence == L'H') + { + Action = 18; + } + + if (*Sequence != L';') return 0; + + Sequence++; + + if ((*Sequence == L'H') || (*Sequence == L'f')) + { + Action = 18; + } + else if (*Sequence == L'r') + { + Action = 19; + } + else + { + if (!VTUTF8ChannelScanForNumber(Sequence, &Number3)) return 0; + + while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++; + + if (*Sequence == L'm') + { + Action = 23; + } + else + { + return 0; + } + } + } + } + } + + Result = Sequence - String + 1; + +ProcessString: + Cursor = (PSAC_CURSOR_DATA)Channel->OBuffer; + VTUTF8ChannelAssertCursor(Channel); + switch (Action) + { + case 0: + if (Channel->CursorRow < Number) + { + Channel->CursorRow = 0; + } + else + { + Channel->CursorRow -= Number; + } + VTUTF8ChannelAssertCursor(Channel); + break; + + case 1: + if (Channel->CursorRow >= SAC_VTUTF8_ROW_HEIGHT) + { + Channel->CursorRow = SAC_VTUTF8_ROW_HEIGHT; + } + else + { + Channel->CursorRow += Number; + } + VTUTF8ChannelAssertCursor(Channel); + break; + + case 3: + if (Channel->CursorCol < Number) + { + Channel->CursorCol = 0; + } + else + { + Channel->CursorCol -= Number; + } + VTUTF8ChannelAssertCursor(Channel); + break; + + case 2: + if (Channel->CursorCol >= SAC_VTUTF8_COL_WIDTH) + { + Channel->CursorCol = SAC_VTUTF8_COL_WIDTH; + } + else + { + Channel->CursorCol += Number; + } + VTUTF8ChannelAssertCursor(Channel); + break; + + case 4: + Channel->CursorVisible = 0; + Channel->CursorX = 40; + Channel->CursorY = 37; + break; + + case 5: + Channel->CursorVisible |= 1; + break; + + case 6: + Channel->CursorVisible &= ~1; + break; + + case 7: + Channel->CursorVisible |= 2; + break; + + case 8: + Channel->CursorVisible &= ~2; + break; + + case 9: + Channel->CursorVisible |= 4; + break; + + case 10: + Channel->CursorVisible &= ~4; + break; + + case 12: + for (i = Channel->CursorCol; i < SAC_VTUTF8_COL_WIDTH; i++) + { + Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) + + (i * SAC_VTUTF8_ROW_HEIGHT)].CursorVisible = Channel->CursorVisible; + Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) + + (i * SAC_VTUTF8_ROW_HEIGHT)].CursorX = Channel->CursorY; + Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) + + (i * SAC_VTUTF8_ROW_HEIGHT)].CursorY = Channel->CursorX; + Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) + + (i * SAC_VTUTF8_ROW_HEIGHT)].CursorValue = ' '; + } + break; + + case 13: + for (i = 0; i < (Channel->CursorCol + 1); i++) + { + Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) + + (i * SAC_VTUTF8_ROW_HEIGHT)].CursorVisible = Channel->CursorVisible; + Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) + + (i * SAC_VTUTF8_ROW_HEIGHT)].CursorX = Channel->CursorY; + Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) + + (i * SAC_VTUTF8_ROW_HEIGHT)].CursorY = Channel->CursorX; + Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) + + (i * SAC_VTUTF8_ROW_HEIGHT)].CursorValue = ' '; + } + break; + + case 14: + for (i = 0; i < SAC_VTUTF8_COL_WIDTH; i++) + { + Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) + + (i * SAC_VTUTF8_ROW_HEIGHT)].CursorVisible = Channel->CursorVisible; + Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) + + (i * SAC_VTUTF8_ROW_HEIGHT)].CursorX = Channel->CursorY; + Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) + + (i * SAC_VTUTF8_ROW_HEIGHT)].CursorY = Channel->CursorX; + Cursor[(Channel->CursorRow * SAC_VTUTF8_COL_WIDTH) + + (i * SAC_VTUTF8_ROW_HEIGHT)].CursorValue = ' '; + } + break; + + case 15: + break; + + case 16: + break; + + case 17: + break; + + case 18: + break; + + case 19: + break; + + case 20: + Channel->CursorY = Number; + Channel->CursorX = Number2; + break; + + case 21: + Channel->CursorX = Number; + break; + + case 22: + Channel->CursorY = Number; + break; + + case 23: + Channel->CursorVisible = Number; + Channel->CursorY = Number2; + Channel->CursorX = Number3; + break; + default: + break; + } + + return Result; +} + +NTSTATUS +NTAPI +VTUTF8ChannelOInit(IN PSAC_CHANNEL Channel) +{ + PSAC_CURSOR_DATA Cursor; + ULONG x, y; + CHECK_PARAMETER(Channel); + + /* Set the current channel cursor parameters */ + Channel->CursorVisible = 0; + Channel->CursorX = 40; + Channel->CursorY = 37; + + /* Loop the output buffer height by width */ + Cursor = (PSAC_CURSOR_DATA)Channel->OBuffer; + y = SAC_VTUTF8_COL_HEIGHT - 1; + do + { + x = SAC_VTUTF8_COL_WIDTH; + do + { + /* For every character, set the defaults */ + Cursor->CursorValue = ' '; + Cursor->CursorX = 40; + Cursor->CursorY = 38; + + /* Move to the next character */ + Cursor++; + } while (--x); + } while (--y); + + /* All done */ + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +VTUTF8ChannelCreate(IN PSAC_CHANNEL Channel) +{ + NTSTATUS Status; + CHECK_PARAMETER(Channel); + + /* Allocate the output buffer */ + Channel->OBuffer = SacAllocatePool(SAC_VTUTF8_OBUFFER_SIZE, GLOBAL_BLOCK_TAG); + CHECK_ALLOCATION(Channel->OBuffer); + + /* Allocate the input buffer */ + Channel->IBuffer = SacAllocatePool(SAC_VTUTF8_IBUFFER_SIZE, GLOBAL_BLOCK_TAG); + CHECK_ALLOCATION(Channel->IBuffer); + + /* Initialize the output stream */ + Status = VTUTF8ChannelOInit(Channel); + if (NT_SUCCESS(Status)) return Status; + + /* Reset all flags and return success */ + _InterlockedExchange(&Channel->ChannelHasNewOBufferData, 0); + _InterlockedExchange(&Channel->ChannelHasNewIBufferData, 0); + return STATUS_SUCCESS; +} + +NTSTATUS +NTAPI +VTUTF8ChannelDestroy(IN PSAC_CHANNEL Channel) +{ + CHECK_PARAMETER(Channel); + + /* Free the buffer and then destroy the channel */ + if (Channel->OBuffer) SacFreePool(Channel->OBuffer); + if (Channel->IBuffer) SacFreePool(Channel->IBuffer); + return ChannelDestroy(Channel); +} + +NTSTATUS +NTAPI +VTUTF8ChannelORead(IN PSAC_CHANNEL Channel, + IN PCHAR Buffer, + IN ULONG BufferSize, + OUT PULONG ByteCount) +{ + return STATUS_NOT_IMPLEMENTED; }
NTSTATUS @@ -180,7 +525,88 @@ IN PCHAR String, IN ULONG Size) { - return STATUS_NOT_IMPLEMENTED; + NTSTATUS Status = STATUS_SUCCESS; + PWSTR pwch; + ULONG i, k, TranslatedCount, UTF8TranslationSize; + BOOLEAN Result; + CHECK_PARAMETER1(Channel); + CHECK_PARAMETER2(String); + + /* Return success if there's nothing to echo */ + if (!(Size / sizeof(WCHAR))) return Status; + + /* Start with the input string*/ + pwch = (PWCHAR)String; + + /* First, figure out how much is outside of the block length alignment */ + k = (Size / sizeof(WCHAR)) % MAX_UTF8_ENCODE_BLOCK_LENGTH; + if (k) + { + /* Translate the misaligned portion */ + Result = SacTranslateUnicodeToUtf8(pwch, + k, + Utf8ConversionBuffer, + Utf8ConversionBufferSize, + &UTF8TranslationSize, + &TranslatedCount); + ASSERT(k == TranslatedCount); + if (!Result) + { + /* If we couldn't translate, write failure to break out below */ + Status = STATUS_UNSUCCESSFUL; + } + else + { + /* Write the misaligned portion into the buffer */ + Status = ConMgrWriteData(Channel, + Utf8ConversionBuffer, + UTF8TranslationSize); + } + + /* If translation or write failed, bail out */ + if (!NT_SUCCESS(Status)) goto Return; + } + + /* Push the string to its new location (this could be a noop if aligned) */ + pwch += k; + + /* Now figure out how many aligned blocks we have, and loop each one */ + k = (Size / sizeof(WCHAR)) / MAX_UTF8_ENCODE_BLOCK_LENGTH; + for (i = 0; i < k; i++) + { + /* Translate the aligned block */ + Result = SacTranslateUnicodeToUtf8(pwch, + MAX_UTF8_ENCODE_BLOCK_LENGTH, + Utf8ConversionBuffer, + Utf8ConversionBufferSize, + &UTF8TranslationSize, + &TranslatedCount); + ASSERT(MAX_UTF8_ENCODE_BLOCK_LENGTH == TranslatedCount); + ASSERT(UTF8TranslationSize > 0); + if (!Result) + { + /* Set failure here, we'll break out below */ + Status = STATUS_UNSUCCESSFUL; + } + else + { + /* Move the string location to the next aligned block */ + pwch += MAX_UTF8_ENCODE_BLOCK_LENGTH; + + /* Write the aligned block into the buffer */ + Status = ConMgrWriteData(Channel, + Utf8ConversionBuffer, + UTF8TranslationSize); + } + + /* If translation or write failed, bail out */ + if (!NT_SUCCESS(Status)) break; + } + +Return: + ASSERT(pwch == (PWSTR)(String + Size)); + if (NT_SUCCESS(Status)) Status = ConMgrFlushData(Channel); + return Status; }
NTSTATUS