mirror of
https://github.com/reactos/reactos.git
synced 2025-01-06 06:20:13 +00:00
[SACDRV]: Start adding definitions/macros/etc based on my reading of ANSI standards (which MS-DOS ANSI.sys of course doesn't respect...). Still WIP. Sources (URLs) listed as appropriate.
svn path=/trunk/; revision=59825
This commit is contained in:
parent
e84d7ea634
commit
5027e45444
3 changed files with 326 additions and 141 deletions
|
@ -14,9 +14,6 @@
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
#define SAC_RAW_OBUFFER_SIZE 0x2000
|
|
||||||
#define SAC_RAW_IBUFFER_SIZE 0x2000
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
NTAPI
|
||||||
RawChannelCreate(IN PSAC_CHANNEL Channel)
|
RawChannelCreate(IN PSAC_CHANNEL Channel)
|
||||||
|
|
|
@ -160,6 +160,10 @@
|
||||||
#define SAC_VTUTF8_COL_HEIGHT 25
|
#define SAC_VTUTF8_COL_HEIGHT 25
|
||||||
#define SAC_VTUTF8_ROW_HEIGHT 24
|
#define SAC_VTUTF8_ROW_HEIGHT 24
|
||||||
#define MAX_UTF8_ENCODE_BLOCK_LENGTH (Utf8ConversionBufferSize / 3 - 1)
|
#define MAX_UTF8_ENCODE_BLOCK_LENGTH (Utf8ConversionBufferSize / 3 - 1)
|
||||||
|
#define SAC_VTUTF8_OBUFFER_SIZE 0x2D00
|
||||||
|
#define SAC_VTUTF8_IBUFFER_SIZE 0x2000
|
||||||
|
#define SAC_RAW_OBUFFER_SIZE 0x2000
|
||||||
|
#define SAC_RAW_IBUFFER_SIZE 0x2000
|
||||||
|
|
||||||
//
|
//
|
||||||
// Channel flags
|
// Channel flags
|
||||||
|
@ -199,6 +203,33 @@ typedef struct _SAC_MESSAGE_ENTRY
|
||||||
PWCHAR Buffer;
|
PWCHAR Buffer;
|
||||||
} SAC_MESSAGE_ENTRY, *PSAC_MESSAGE_ENTRY;
|
} SAC_MESSAGE_ENTRY, *PSAC_MESSAGE_ENTRY;
|
||||||
|
|
||||||
|
//
|
||||||
|
// These are the VT-100/220/ANSI Escape Codes supported by SAC
|
||||||
|
//
|
||||||
|
typedef enum _SAC_ANSI_COMMANDS
|
||||||
|
{
|
||||||
|
SacCursorUp,
|
||||||
|
SacCursorDown,
|
||||||
|
SacCursorRight,
|
||||||
|
SacCursorLeft,
|
||||||
|
SacFontNormal,
|
||||||
|
SacFontBlink,
|
||||||
|
SacFontBlinkOff,
|
||||||
|
SacFontBold,
|
||||||
|
SacFontBoldOff,
|
||||||
|
SacFontInverse,
|
||||||
|
SacFontInverseOff,
|
||||||
|
SacBackTab,
|
||||||
|
SacEraseEndOfLine,
|
||||||
|
SacEraseStartOfLine,
|
||||||
|
SacEraseLine,
|
||||||
|
SacEraseEndOfScreen,
|
||||||
|
SacEraseStartOfScreen,
|
||||||
|
SacEraseScreen,
|
||||||
|
SacSetBackgroundColor = 21,
|
||||||
|
SacSetFontColor
|
||||||
|
} SAC_ANSI_COMMANDS;
|
||||||
|
|
||||||
//
|
//
|
||||||
// SAC supports 3 different channel output types
|
// SAC supports 3 different channel output types
|
||||||
//
|
//
|
||||||
|
@ -236,6 +267,28 @@ typedef struct _SAC_CHANNEL_LOCK
|
||||||
KSEMAPHORE Lock;
|
KSEMAPHORE Lock;
|
||||||
} SAC_CHANNEL_LOCK, *PSAC_CHANNEL_LOCK;
|
} SAC_CHANNEL_LOCK, *PSAC_CHANNEL_LOCK;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Structure of the cell-buffer when in VT-UTF8 Mode
|
||||||
|
//
|
||||||
|
typedef struct _SAC_CURSOR_DATA
|
||||||
|
{
|
||||||
|
UCHAR CursorX;
|
||||||
|
UCHAR CursorY;
|
||||||
|
UCHAR CursorVisible;
|
||||||
|
WCHAR CursorValue;
|
||||||
|
} SAC_CURSOR_DATA, *PSAC_CURSOR_DATA;
|
||||||
|
C_ASSERT(sizeof(SAC_CURSOR_DATA) == 6);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Small optimization to easily recognize the most common VT-100/ANSI codes
|
||||||
|
//
|
||||||
|
typedef struct _SAC_STATIC_ESCAPE_STRING
|
||||||
|
{
|
||||||
|
WCHAR Sequence[10];
|
||||||
|
ULONG Size;
|
||||||
|
ULONG Action;
|
||||||
|
} SAC_STATIC_ESCAPE_STRING, *PSAC_STATIC_ESCAPE_STRING;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Channel callbacks
|
// Channel callbacks
|
||||||
//
|
//
|
||||||
|
|
|
@ -17,41 +17,166 @@ WCHAR IncomingUnicodeValue;
|
||||||
|
|
||||||
/* FUNCTIONS *****************************************************************/
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
typedef struct _SAC_CURSOR_DATA
|
//
|
||||||
|
// Source: http://en.wikipedia.org/wiki/ANSI_escape_code
|
||||||
|
//
|
||||||
|
typedef enum _VT_ANSI_ATTRIBUTES
|
||||||
{
|
{
|
||||||
UCHAR CursorX;
|
//
|
||||||
UCHAR CursorY;
|
// Attribute modifiers (mostly supported)
|
||||||
UCHAR CursorVisible;
|
//
|
||||||
WCHAR CursorValue;
|
Normal,
|
||||||
} SAC_CURSOR_DATA, *PSAC_CURSOR_DATA;
|
Bold,
|
||||||
|
Faint,
|
||||||
|
Italic,
|
||||||
|
Underline,
|
||||||
|
SlowBlink,
|
||||||
|
FastBlink,
|
||||||
|
Inverse,
|
||||||
|
Conceal,
|
||||||
|
Strikethrough,
|
||||||
|
|
||||||
C_ASSERT(sizeof(SAC_CURSOR_DATA) == 6);
|
//
|
||||||
|
// Font selectors (not supported)
|
||||||
|
//
|
||||||
|
PrimaryFont,
|
||||||
|
AlternateFont1,
|
||||||
|
AlternateFont2,
|
||||||
|
AlternateFont3,
|
||||||
|
Alternatefont4,
|
||||||
|
AlteronateFont5,
|
||||||
|
AlteronateFont6,
|
||||||
|
AlternateFont7,
|
||||||
|
AlternatEfont8,
|
||||||
|
Alternatefont9,
|
||||||
|
|
||||||
typedef struct _SAC_STATIC_ESCAPE_STRING
|
//
|
||||||
{
|
// Additional attributes (not supported)
|
||||||
WCHAR Sequence[10];
|
//
|
||||||
ULONG Size;
|
Fraktur,
|
||||||
ULONG Action;
|
DoubleUnderline,
|
||||||
} SAC_STATIC_ESCAPE_STRING, *PSAC_STATIC_ESCAPE_STRING;
|
|
||||||
|
//
|
||||||
|
// 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';'
|
||||||
|
|
||||||
SAC_STATIC_ESCAPE_STRING SacStaticEscapeStrings [] =
|
SAC_STATIC_ESCAPE_STRING SacStaticEscapeStrings [] =
|
||||||
{
|
{
|
||||||
{ L"[A", 2, 0 },
|
{ VT_ANSI_CURSOR_UP, 2, SacCursorUp },
|
||||||
{ L"[B", 2, 1 },
|
{ VT_ANSI_CURSOR_DOWN, 2, SacCursorDown },
|
||||||
{ L"[C", 2, 2 },
|
{ VT_ANSI_CURSOR_RIGHT, 2, SacCursorRight },
|
||||||
{ L"[D", 2, 3 },
|
{ VT_ANSI_CURSOR_LEFT, 2, SacCursorLeft },
|
||||||
{ L"[0Z", 3, 11 },
|
{ VT_220_BACKTAB, 3, SacBackTab },
|
||||||
{ L"[K", 2, 12 },
|
{ VT_ANSI_ERASE_END_LINE, 2, SacEraseEndOfLine },
|
||||||
{ L"[1K", 3, 13 },
|
{ VT_ANSI_ERASE_START_LINE, 3, SacEraseStartOfLine },
|
||||||
{ L"[2K", 3, 14 },
|
{ VT_ANSI_ERASE_ENTIRE_LINE, 3, SacEraseLine },
|
||||||
{ L"[J", 2, 15 },
|
{ VT_ANSI_ERASE_DOWN_SCREEN, 2, SacEraseEndOfScreen },
|
||||||
{ L"[1J", 3, 16 },
|
{ VT_ANSI_ERASE_UP_SCREEN, 3, SacEraseStartOfScreen },
|
||||||
{ L"[2J", 3, 17 },
|
{ VT_ANSI_ERASE_ENTIRE_SCREEN, 3, SacEraseScreen },
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SAC_VTUTF8_OBUFFER_SIZE 0x2D00
|
|
||||||
#define SAC_VTUTF8_IBUFFER_SIZE 0x2000
|
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
NTAPI
|
NTAPI
|
||||||
VTUTF8ChannelScanForNumber(IN PWCHAR String,
|
VTUTF8ChannelScanForNumber(IN PWCHAR String,
|
||||||
|
@ -105,6 +230,9 @@ VTUTF8ChannelAssertCursor(IN PSAC_CHANNEL Channel)
|
||||||
ASSERT(Channel->CursorCol < SAC_VTUTF8_COL_WIDTH);
|
ASSERT(Channel->CursorCol < SAC_VTUTF8_COL_WIDTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Not a
|
||||||
|
//
|
||||||
ULONG
|
ULONG
|
||||||
NTAPI
|
NTAPI
|
||||||
VTUTF8ChannelConsumeEscapeSequence(IN PSAC_CHANNEL Channel,
|
VTUTF8ChannelConsumeEscapeSequence(IN PSAC_CHANNEL Channel,
|
||||||
|
@ -113,7 +241,7 @@ VTUTF8ChannelConsumeEscapeSequence(IN PSAC_CHANNEL Channel,
|
||||||
ULONG Number, Number2, Number3, i, Action, Result;
|
ULONG Number, Number2, Number3, i, Action, Result;
|
||||||
PWCHAR Sequence;
|
PWCHAR Sequence;
|
||||||
PSAC_CURSOR_DATA Cursor;
|
PSAC_CURSOR_DATA Cursor;
|
||||||
ASSERT(String[0] == L'\x1B');
|
ASSERT(String[0] == VT_ANSI_ESCAPE);
|
||||||
|
|
||||||
for (i = 0; i < RTL_NUMBER_OF(SacStaticEscapeStrings); i++)
|
for (i = 0; i < RTL_NUMBER_OF(SacStaticEscapeStrings); i++)
|
||||||
{
|
{
|
||||||
|
@ -128,133 +256,140 @@ VTUTF8ChannelConsumeEscapeSequence(IN PSAC_CHANNEL Channel,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (String[1] != L'[') return 0;
|
if (String[1] != VT_ANSI_COMMAND) return 0;
|
||||||
|
|
||||||
|
Result = 0;
|
||||||
Sequence = String + 2;
|
Sequence = String + 2;
|
||||||
switch (*Sequence)
|
switch (*Sequence)
|
||||||
{
|
{
|
||||||
case L'A':
|
case VT_ANSI_CURSOR_UP_CHAR:
|
||||||
Action = 0;
|
Action = SacCursorUp;
|
||||||
break;
|
goto ProcessString;
|
||||||
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;
|
|
||||||
|
|
||||||
|
case VT_ANSI_CURSOR_DOWN_CHAR:
|
||||||
|
Action = SacCursorDown;
|
||||||
|
goto ProcessString;
|
||||||
|
|
||||||
|
case VT_ANSI_CURSOR_RIGHT_CHAR:
|
||||||
|
Action = SacCursorLeft; //bug
|
||||||
|
goto ProcessString;
|
||||||
|
|
||||||
|
case VT_ANSI_CURSOR_LEFT_CHAR:
|
||||||
|
Action = SacCursorRight; //bug
|
||||||
|
goto ProcessString;
|
||||||
|
|
||||||
|
case VT_ANSI_ERASE_LINE_CHAR:
|
||||||
|
Action = SacEraseEndOfLine;
|
||||||
|
goto ProcessString;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!VTUTF8ChannelScanForNumber(Sequence, &Number)) return 0;
|
||||||
while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++;
|
while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++;
|
||||||
|
|
||||||
if (*Sequence == 'm')
|
if (*Sequence == VT_ANSI_SET_ATTRIBUTE_CHAR)
|
||||||
{
|
{
|
||||||
switch (Number)
|
switch (Number)
|
||||||
{
|
{
|
||||||
case 0:
|
case Normal:
|
||||||
Action = 4;
|
Action = SacFontNormal;
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
Action = 7;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case Bold:
|
||||||
Action = 5;
|
Action = SacFontBold;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7:
|
case SlowBlink:
|
||||||
Action = 9;
|
Action = SacFontBlink;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 22:
|
case Inverse:
|
||||||
Action = 8;
|
Action = SacFontInverse;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 25:
|
case BoldOff:
|
||||||
Action = 6;
|
Action = SacFontBoldOff;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 27:
|
case BlinkOff:
|
||||||
Action = 10;
|
Action = SacFontBlinkOff;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InverseOff:
|
||||||
|
Action = SacFontInverseOff;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if ((Number < 40) || (Number > 47))
|
if ((Number < SetBackColorStart) || (Number > SetBackColorMax))
|
||||||
{
|
{
|
||||||
if ((Number < 30) || (Number > 39))
|
if ((Number < SetColorStart) || (Number > SetColorMax))
|
||||||
{
|
{
|
||||||
ASSERT(FALSE);
|
ASSERT(FALSE);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Action = 22;
|
Action = SacSetFontColor;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Action = 21;
|
Action = SacSetBackgroundColor;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
goto ProcessString;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
if (*Sequence != VT_ANSI_SEPARATOR_CHAR) return 0;
|
||||||
if (*Sequence != L';') return 0;
|
|
||||||
Sequence++;
|
Sequence++;
|
||||||
|
|
||||||
if (!VTUTF8ChannelScanForNumber(Sequence, &Number2)) return 0;
|
if (!VTUTF8ChannelScanForNumber(Sequence, &Number2)) return 0;
|
||||||
|
|
||||||
while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++;
|
while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++;
|
||||||
|
|
||||||
if (*Sequence == L'm')
|
if (*Sequence == VT_ANSI_SET_ATTRIBUTE_CHAR)
|
||||||
{
|
{
|
||||||
Action = 20;
|
Action = 20;
|
||||||
|
goto ProcessString;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (*Sequence == L'H')
|
if (*Sequence == L'H')
|
||||||
{
|
{
|
||||||
Action = 18;
|
Action = 18;
|
||||||
|
goto ProcessString;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*Sequence != L';') return 0;
|
if (*Sequence != VT_ANSI_SEPARATOR_CHAR) return 0;
|
||||||
|
|
||||||
Sequence++;
|
Sequence++;
|
||||||
|
|
||||||
if ((*Sequence == L'H') || (*Sequence == L'f'))
|
if ((*Sequence == L'H') || (*Sequence == L'f'))
|
||||||
{
|
{
|
||||||
Action = 18;
|
Action = 18;
|
||||||
|
goto ProcessString;
|
||||||
}
|
}
|
||||||
else if (*Sequence == L'r')
|
|
||||||
|
if (*Sequence == L'r')
|
||||||
{
|
{
|
||||||
Action = 19;
|
Action = 19;
|
||||||
|
goto ProcessString;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!VTUTF8ChannelScanForNumber(Sequence, &Number3)) return 0;
|
|
||||||
|
|
||||||
|
if (!VTUTF8ChannelScanForNumber(Sequence, &Number3)) return 0;
|
||||||
while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++;
|
while ((*Sequence >= L'0') && (*Sequence <= L'9')) Sequence++;
|
||||||
|
|
||||||
if (*Sequence == L'm')
|
if (*Sequence == VT_ANSI_SET_ATTRIBUTE_CHAR)
|
||||||
{
|
{
|
||||||
Action = 23;
|
Action = 23;
|
||||||
}
|
goto ProcessString;
|
||||||
else
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Result = Sequence - String + 1;
|
return 0;
|
||||||
|
|
||||||
ProcessString:
|
ProcessString:
|
||||||
|
if (!Result) Result = Sequence - String + 1;
|
||||||
|
|
||||||
Cursor = (PSAC_CURSOR_DATA)Channel->OBuffer;
|
Cursor = (PSAC_CURSOR_DATA)Channel->OBuffer;
|
||||||
VTUTF8ChannelAssertCursor(Channel);
|
VTUTF8ChannelAssertCursor(Channel);
|
||||||
switch (Action)
|
switch (Action)
|
||||||
|
|
Loading…
Reference in a new issue