[SACDRV]: Implement VTUTF8ChannelScanForNumber.

[SACDRV]: Implement VTUTF8ChannelOEcho.
[SACDRV]: WIP-lement VTUTF8ChannelConsumeEscapeSequence. Have to do some reading up on ANSI to get this right.

svn path=/trunk/; revision=59824
This commit is contained in:
Alex Ionescu 2013-08-25 21:56:20 +00:00
parent abedd40dd8
commit e84d7ea634
2 changed files with 489 additions and 50 deletions

View file

@ -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 @@ VerifyEventWaitable(
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
//

View file

@ -27,9 +27,398 @@ typedef struct _SAC_CURSOR_DATA
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
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 TRUE;
}
NTSTATUS
NTAPI
VTUTF8ChannelAnsiDispatch(
IN NTSTATUS Status,
IN ULONG AnsiCode,
IN PWCHAR Data,
IN ULONG Length
)
{
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
VTUTF8ChannelProcessAttributes(
IN PSAC_CHANNEL Channel,
IN UCHAR Attribute
)
{
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)
@ -104,56 +493,12 @@ VTUTF8ChannelDestroy(IN PSAC_CHANNEL Channel)
NTSTATUS
NTAPI
VTUTF8ChannelORead(
IN PSAC_CHANNEL Channel,
IN PCHAR Buffer,
IN ULONG BufferSize,
OUT PULONG ByteCount
)
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;
}
NTSTATUS
NTAPI
VTUTF8ChannelAnsiDispatch(
IN NTSTATUS Status,
IN ULONG AnsiCode,
IN PWCHAR Data,
IN ULONG Length
)
{
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
VTUTF8ChannelProcessAttributes(
IN PSAC_CHANNEL Channel,
IN UCHAR Attribute
)
{
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
NTAPI
VTUTF8ChannelConsumeEscapeSequence(
IN PSAC_CHANNEL Channel,
IN PWCHAR String
)
{
return STATUS_NOT_IMPLEMENTED;
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS
@ -180,7 +525,88 @@ VTUTF8ChannelOEcho(IN PSAC_CHANNEL Channel,
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