You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4192 lines
113 KiB
4192 lines
113 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
parse.c
|
|
|
|
Abstract:
|
|
|
|
This module contains UI code for the OS chooser
|
|
|
|
Author:
|
|
|
|
Adam Barr (adamba) 15-May-1997
|
|
|
|
Revision History:
|
|
|
|
Geoff Pease (GPease) 28 May 1998 - Major Overhaul to "OSCML" parser
|
|
|
|
--*/
|
|
|
|
#ifdef i386
|
|
#include "bldrx86.h"
|
|
#endif
|
|
|
|
#if defined(_IA64_)
|
|
#include "bldria64.h"
|
|
#endif
|
|
|
|
|
|
#include "ctype.h"
|
|
#include "stdio.h"
|
|
#include "string.h"
|
|
#include <netfs.h>
|
|
#include "oscheap.h"
|
|
#include "parse.h"
|
|
#include "hdlsterm.h"
|
|
|
|
|
|
#if 0 && DBG==1
|
|
#define _TRACE_FUNC_
|
|
#endif
|
|
|
|
#ifdef _TRACE_FUNC_
|
|
#define TraceFunc( _func) { \
|
|
CHAR FileLine[80]; \
|
|
sprintf( FileLine, "%s(%u)", __FILE__, __LINE__ ); \
|
|
DPRINT( OSC, ("%-55s: %s", FileLine, _func) ); \
|
|
}
|
|
#else
|
|
#define TraceFunc( _func )
|
|
#endif
|
|
|
|
#define SCREEN_TOP 2
|
|
#ifdef EFI
|
|
#define SCREEN_BOTTOM 24
|
|
#else
|
|
#define SCREEN_BOTTOM 25
|
|
#endif
|
|
|
|
// Special translated character codes
|
|
#define CHAR_NBSP ((CHAR)255)
|
|
|
|
#define MAX_INPUT_BUFFER_LENGTH 1024
|
|
|
|
#define PRINT(s,l) { ULONG privCount; ArcWrite(BlConsoleOutDeviceId, (s), (l), &privCount); }
|
|
#define PRINTL(s) { ULONG privCount; ArcWrite(BlConsoleOutDeviceId, (s), _tcslen(s), &privCount); }
|
|
|
|
#define BLINK_RATE 5
|
|
#define BRACKETS 4 // left and right brackets w/one space each
|
|
|
|
#define CT_TEXT 0x1
|
|
#define CT_PASSWORD 0x2
|
|
#define CT_RESET 0x4
|
|
#define CT_SELECT 0x8
|
|
#define CT_OPTION 0x10
|
|
#define CT_LOCAL 0x20
|
|
#define CT_VARIABLE 0x40
|
|
|
|
enum ENCODETYPE {
|
|
ET_NONE = 0,
|
|
ET_OWF
|
|
};
|
|
|
|
typedef struct {
|
|
enum ACTIONS Action;
|
|
PCHAR ScreenName;
|
|
} KEY_RESPONSE, *LPKEY_RESPONSE;
|
|
|
|
|
|
typedef struct {
|
|
void * Next;
|
|
enum CONTROLTYPE Type;
|
|
} CONTROLSTRUCT, *LPCONTROLSTRUCT;
|
|
|
|
typedef struct {
|
|
void * Next;
|
|
int Type;
|
|
enum ENCODETYPE Encoding;
|
|
int Size;
|
|
int MaxLength;
|
|
int X;
|
|
int Y;
|
|
int CurrentPosition;
|
|
int FirstVisibleChar;
|
|
PCHAR Name;
|
|
PCHAR Value;
|
|
} INPUTSTRUCT, *LPINPUTSTRUCT;
|
|
|
|
enum OPTIONFLAGS {
|
|
OF_MULTIPLE = 0x01,
|
|
OF_SELECTED = 0x02,
|
|
};
|
|
|
|
typedef struct {
|
|
void * Next;
|
|
enum CONTROLTYPE Type;
|
|
enum OPTIONFLAGS Flags;
|
|
PCHAR Value;
|
|
PCHAR Displayed;
|
|
PCHAR Tip;
|
|
PCHAR EndTip;
|
|
} OPTIONSTRUCT, * LPOPTIONSTRUCT;
|
|
|
|
typedef struct {
|
|
void * Next;
|
|
enum CONTROLTYPE Type;
|
|
enum OPTIONFLAGS Flags;
|
|
int Size;
|
|
int X;
|
|
int Y;
|
|
int Width;
|
|
int Timeout;
|
|
BOOLEAN AutoSelect;
|
|
PCHAR Name;
|
|
LPOPTIONSTRUCT FirstVisibleSelection;
|
|
LPOPTIONSTRUCT CurrentSelection;
|
|
} SELECTSTRUCT, * LPSELECTSTRUCT;
|
|
|
|
typedef struct {
|
|
int X;
|
|
int Y;
|
|
int LeftMargin;
|
|
int RightMargin;
|
|
int Size;
|
|
} TIPAREA, *LPTIPAREA;
|
|
|
|
extern const CHAR rghex[]; // "0123456789ABCDEF"
|
|
|
|
//
|
|
// Current Screen Paramaters
|
|
//
|
|
PCHAR ScreenAttributes;
|
|
static CHAR WhiteOnBlueAttributes[] = ";44;37m"; // normal text, white on blue
|
|
static CHAR BlackOnBlackAttributes[] = ";40;40m"; // normal text, black on black
|
|
int ScreenX;
|
|
int ScreenY;
|
|
int ScreenBottom;
|
|
int LeftMargin;
|
|
int RightMargin;
|
|
LPKEY_RESPONSE EnterKey;
|
|
LPKEY_RESPONSE EscKey;
|
|
LPKEY_RESPONSE F1Key;
|
|
LPKEY_RESPONSE F3Key;
|
|
BOOLEAN PreformattedMode;
|
|
BOOLEAN LoginScreen;
|
|
BOOLEAN AutoEnter;
|
|
BOOLEAN InsertMode;
|
|
void * ScreenControls;
|
|
enum ACTIONS SpecialAction;
|
|
LPTIPAREA TipArea;
|
|
|
|
#if defined(PLEASE_WAIT)
|
|
PCHAR PleaseWaitMsg;
|
|
#endif
|
|
|
|
// 80 spaces, for padding out menu bar highlights.
|
|
static TCHAR SpaceString[] =
|
|
TEXT(" ");
|
|
|
|
//
|
|
// used to track the type of authentication we should try.
|
|
//
|
|
ULONG AuthenticationType;
|
|
|
|
VOID
|
|
RomDumpRawData (
|
|
IN PUCHAR DataStart,
|
|
IN ULONG DataLength,
|
|
IN ULONG Offset
|
|
);
|
|
|
|
//
|
|
// From regboot.c -- Column and Row are 1-based
|
|
//
|
|
|
|
VOID
|
|
BlpPositionCursor(
|
|
IN ULONG Column,
|
|
IN ULONG Row
|
|
);
|
|
|
|
VOID
|
|
BlpClearScreen(
|
|
VOID
|
|
);
|
|
//
|
|
// End from regboot.c
|
|
//
|
|
|
|
|
|
|
|
//
|
|
// Gets an integer, using PrevLoc and CurLoc as in BlProcessScreen.
|
|
//
|
|
UINT
|
|
GetInteger(
|
|
PCHAR * InputString
|
|
)
|
|
{
|
|
UINT uint;
|
|
PCHAR psz;
|
|
|
|
TraceFunc( "BlpGetInteger()\n" );
|
|
|
|
uint = 0;
|
|
psz = *InputString;
|
|
|
|
while ((*psz >= '0') && (*psz <= '9')) {
|
|
uint = (uint*10) + *psz - '0';
|
|
++psz;
|
|
}
|
|
*InputString = psz;
|
|
|
|
//DPRINT( OSC, ("Integer: '%u'\n", tmpInteger) );
|
|
return uint;
|
|
}
|
|
|
|
|
|
|
|
#ifdef EFI
|
|
BlpShowCursor(
|
|
IN BOOLEAN ShowCursor,
|
|
IN TCHAR UnderCharacter
|
|
)
|
|
{
|
|
//bugbug handle "under character"
|
|
BlEfiEnableCursor(ShowCursor);
|
|
|
|
}
|
|
|
|
VOID
|
|
BlpSendEscape(
|
|
PCHAR Escape
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sends an escape to the screen.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
BlEfiSetAttribute(DEFATT);
|
|
BlEfiSetInverseMode(FALSE);
|
|
}
|
|
|
|
|
|
VOID
|
|
BlpSendEscapeReverse(
|
|
PCHAR Escape
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sends an escape to the screen that reverses the foreground and
|
|
background colors of the Escape sequence. All special codes are
|
|
retained (codes not in the ranges of 30-37 and 40-47).
|
|
|
|
Arguments:
|
|
|
|
Escape - the escape sequence string.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
BlEfiSetAttribute(INVATT);
|
|
}
|
|
|
|
VOID
|
|
BlpSendEscapeBold(
|
|
PCHAR Escape
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sends an escape to the screen with the additional inverse code.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
NOTHING;
|
|
}
|
|
|
|
VOID
|
|
BlpSendEscapeFlash(
|
|
PCHAR Escape
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sends an escape to the screen with the additional flash code.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
NOTHING; //there is no flash attribute available under EFI.
|
|
}
|
|
|
|
|
|
#else
|
|
|
|
VOID
|
|
BlpSendEscape(
|
|
PCHAR Escape
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sends an escape to the screen.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
TCHAR Buffer[16];
|
|
ULONG Count;
|
|
|
|
#ifdef _TRACE_FUNC_
|
|
TraceFunc("BlpSendEscape( ");
|
|
DPRINT( OSC, ("Escape='%s' )\n", Escape) );
|
|
#endif
|
|
|
|
#ifdef UNICODE
|
|
_stprintf(Buffer, TEXT("%s%S"), ASCI_CSI_OUT, Escape);
|
|
#else
|
|
_stprintf(Buffer, TEXT("%s%s"), ASCI_CSI_OUT, Escape);
|
|
#endif
|
|
|
|
PRINTL(Buffer);
|
|
}
|
|
|
|
|
|
VOID
|
|
BlpSendEscapeReverse(
|
|
PCHAR Escape
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sends an escape to the screen that reverses the foreground and
|
|
background colors of the Escape sequence. All special codes are
|
|
retained (codes not in the ranges of 30-37 and 40-47).
|
|
|
|
Arguments:
|
|
|
|
Escape - the escape sequence string.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
TCHAR Buffer[20];
|
|
PCHAR CurLoc = Escape;
|
|
int Color;
|
|
|
|
#ifdef _TRACE_FUNC_
|
|
TraceFunc( "BlpSendEscapeReverse( " );
|
|
DPRINT( OSC, ("Escape='%s' )\n", Escape) );
|
|
#endif
|
|
|
|
if ( Escape == NULL ) {
|
|
return; // abort
|
|
}
|
|
|
|
_tcscpy( Buffer, ASCI_CSI_OUT );
|
|
|
|
//
|
|
// Pre-pend the inverse video string for a vt100 terminal
|
|
//
|
|
if (BlIsTerminalConnected()) {
|
|
_stprintf(Buffer, TEXT("%s7"), Buffer);
|
|
}
|
|
|
|
while ( *CurLoc && *CurLoc != 'm' ) {
|
|
if ( !( *CurLoc >= '0' && *CurLoc <= '9' ) ) {
|
|
CurLoc++;
|
|
}
|
|
|
|
Color = GetInteger( &CurLoc );
|
|
|
|
if ( Color >=30 && Color <= 37) {
|
|
Color += 10;
|
|
} else if ( Color >= 40 && Color <= 47 ) {
|
|
Color -= 10;
|
|
}
|
|
|
|
_stprintf( Buffer, TEXT("%s;%u"), Buffer, Color );
|
|
}
|
|
|
|
//
|
|
// Add trailing 'm'
|
|
//
|
|
_stprintf( Buffer, TEXT("%sm"), Buffer );
|
|
|
|
PRINTL( Buffer );
|
|
}
|
|
|
|
VOID
|
|
BlpSendEscapeBold(
|
|
PCHAR Escape
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sends an escape to the screen with the additional inverse code.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
TCHAR Buffer[20];
|
|
|
|
#ifdef _TRACE_FUNC_
|
|
TraceFunc( "BlpSendEscapeBold( " );
|
|
DPRINT( OSC, ("Escape='%s' )\n", Escape) );
|
|
#endif
|
|
|
|
_stprintf(Buffer, TEXT("%s;1%s"), ASCI_CSI_OUT, Escape);
|
|
PRINTL(Buffer);
|
|
}
|
|
|
|
VOID
|
|
BlpSendEscapeFlash(
|
|
PCHAR Escape
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Sends an escape to the screen with the additional flash code.
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
TCHAR Buffer[20];
|
|
|
|
#ifdef _TRACE_FUNC_
|
|
TraceFunc( "BlpSendEscapeFlash( " );
|
|
DPRINT( OSC, ("Escape='%s' )\n", Escape) );
|
|
#endif
|
|
|
|
_stprintf(Buffer, TEXT("%s;5%s"), ASCI_CSI_OUT, Escape);
|
|
PRINTL(Buffer);
|
|
}
|
|
|
|
//
|
|
// BlpShowCursor( )
|
|
//
|
|
VOID
|
|
BlpShowCursor(
|
|
IN BOOLEAN ShowCursor,
|
|
IN TCHAR UnderCharacter )
|
|
{
|
|
TCHAR Buffer[20];
|
|
|
|
if (ShowCursor) {
|
|
if(InsertMode){
|
|
_stprintf(Buffer,TEXT("5%s"),ScreenAttributes);
|
|
BlpSendEscapeReverse(Buffer);
|
|
}
|
|
else{
|
|
_stprintf(Buffer,TEXT("5%s"),ScreenAttributes);
|
|
BlpSendEscape(Buffer);
|
|
}
|
|
} else {
|
|
_stprintf(Buffer,TEXT("0%s"),ScreenAttributes);
|
|
BlpSendEscape(Buffer);
|
|
}
|
|
|
|
if (UnderCharacter) {
|
|
PRINT( &UnderCharacter, sizeof(TCHAR));
|
|
} else {
|
|
if((InsertMode == FALSE )&& ShowCursor){
|
|
PRINT(TEXT("_"),sizeof(TCHAR));
|
|
return;
|
|
}
|
|
if(ShowCursor){
|
|
PRINT(TEXT("Û"),sizeof(TCHAR));
|
|
return;
|
|
}
|
|
PRINT(TEXT(" "),sizeof(TCHAR));
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// BlpGetKey()
|
|
//
|
|
// Calls BlGetKey(), but checks if this screen has "auto-enter"
|
|
// turned on in which case it will return an enter key once.
|
|
//
|
|
ULONG
|
|
BlpGetKey(
|
|
VOID
|
|
)
|
|
{
|
|
if (AutoEnter) {
|
|
return ENTER_KEY;
|
|
AutoEnter = FALSE; // only return it once per screen
|
|
} else {
|
|
return BlGetKey();
|
|
}
|
|
}
|
|
|
|
//
|
|
// BlpGetKeyWithBlink( )
|
|
//
|
|
// Displays a blinking cursor as the X,Y coordinates given and awaits
|
|
// a key press.
|
|
//
|
|
ULONG
|
|
BlpGetKeyWithBlink(
|
|
IN ULONG XLocation,
|
|
IN ULONG YLocation,
|
|
IN TCHAR UnderCharacter
|
|
)
|
|
{
|
|
ULONG Key = 0;
|
|
|
|
TraceFunc("BlpGetKeyWithBlink()\n");
|
|
|
|
BlpPositionCursor(XLocation, YLocation);
|
|
BlpShowCursor( TRUE, UnderCharacter );
|
|
|
|
do {
|
|
|
|
Key = BlpGetKey();
|
|
|
|
} while (Key == 0);
|
|
|
|
BlpPositionCursor(XLocation, YLocation);
|
|
BlpShowCursor( FALSE, UnderCharacter );
|
|
|
|
return Key;
|
|
}
|
|
|
|
//
|
|
// BlpPrintString( )
|
|
//
|
|
// Prints out a large string to the display. It also wraps the text as
|
|
// needed.
|
|
//
|
|
void
|
|
BlpPrintString(
|
|
IN PCHAR Start,
|
|
IN PCHAR End
|
|
)
|
|
{
|
|
PTCHAR Scan;
|
|
PTCHAR PrintBuf;
|
|
PTCHAR pStart;
|
|
PTCHAR pEnd;
|
|
ULONG i;
|
|
TCHAR TmpChar;
|
|
int Length = 0;
|
|
|
|
|
|
DPRINT( OSC, ("BlpPrintString: Start = 0x%08x, End = 0x%08x, Length = %d\n", Start, End, (ULONG)(End - Start)) );
|
|
DPRINT( OSC, ("[BlockPrint, Length=%u] '%s'\n", (ULONG)(End - Start), Start) );
|
|
|
|
while ( Start < End && *Start == 32 )
|
|
Start++;
|
|
|
|
if ( Start == End )
|
|
return; // NOP
|
|
|
|
// Copy the buffer so if something goes wrong, the orginal
|
|
// screen will still be intact.
|
|
|
|
Length = (int)(End - Start);
|
|
PrintBuf = (PTCHAR)OscHeapAlloc( Length*sizeof(TCHAR) );
|
|
|
|
if (!PrintBuf) {
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < (ULONG)Length; i++) {
|
|
PrintBuf[i] = (TCHAR)Start[i];
|
|
if (PrintBuf[i] & 0x80) {
|
|
DPRINT( OSC, ("BlpPrintString: covering non-printable character %04lx\r\n", (USHORT)PrintBuf[i]) );
|
|
PrintBuf[i] = (TCHAR)32;
|
|
}
|
|
}
|
|
|
|
pStart = PrintBuf;
|
|
pEnd = pStart + Length;
|
|
|
|
BlpPositionCursor( ScreenX, ScreenY );
|
|
|
|
// See if it is short enough to do the quick route
|
|
if ( Length + ScreenX <= RightMargin ) {
|
|
#if DBG
|
|
{
|
|
TmpChar = *pEnd;
|
|
*pEnd = 0;
|
|
DPRINT( OSC, ("[BlockPrint, Short] '%s'\n", pStart) );
|
|
*pEnd = TmpChar;
|
|
}
|
|
#endif
|
|
PRINT( pStart, Length*sizeof(TCHAR) );
|
|
ScreenX += Length;
|
|
} else {
|
|
|
|
while( (pStart < pEnd) && (ScreenY <= ScreenBottom) )
|
|
{
|
|
DPRINT(
|
|
OSC,
|
|
("BlpPrintString: About to print a line.\r\n") );
|
|
DPRINT(
|
|
OSC,
|
|
(" pStart: 0x%08lx pEnd: 0x%08lx PrintBuf: 0x%08lx\r\n",
|
|
PtrToUint(pStart),
|
|
PtrToUint(pEnd),
|
|
PtrToUint(PrintBuf)) );
|
|
|
|
//
|
|
// Jump over NULL strings.
|
|
//
|
|
if( *pStart == TEXT('\0') ) {
|
|
pStart++;
|
|
break;
|
|
}
|
|
|
|
Length = (ULONG)(pEnd - pStart);
|
|
DPRINT( OSC, ("BlpPrint: I think the length of this string is %d\n", Length) );
|
|
|
|
// do nice wrapping
|
|
if ( Length > RightMargin - ScreenX ) {
|
|
|
|
Length = RightMargin - ScreenX;
|
|
DPRINT( OSC, ("BlpPrint: I'm going to truncate the length because it's too big. Now it's %d\n", Length) );
|
|
|
|
// try to find a "break" character
|
|
while ( Length && pStart[Length] != (TCHAR)32 ) {
|
|
Length--;
|
|
}
|
|
|
|
DPRINT( OSC, ("BlpPrint: After jumping over the whitespace, it's %d\n", Length) );
|
|
|
|
|
|
// If we can't "break" it, just dump one line's worth
|
|
if ( !Length ) {
|
|
DPRINT( OSC, ("[BlockPrint Length == 0, Dumping a lines worth]\n") );
|
|
Length = RightMargin - ScreenX;
|
|
}
|
|
}
|
|
|
|
#if DBG
|
|
{
|
|
TmpChar = pStart[Length];
|
|
pStart[Length] = 0;
|
|
#ifdef UNICODE
|
|
DPRINT( OSC, ("[BlockPrint, Length=%u] '%ws'\n", Length, pStart) );
|
|
#else
|
|
DPRINT( OSC, ("[BlockPrint, Length=%u] '%s'\n", Length, pStart) );
|
|
#endif
|
|
pStart[Length] = TmpChar;
|
|
}
|
|
#endif
|
|
BlpPositionCursor( ScreenX, ScreenY );
|
|
PRINT( pStart, Length*sizeof(TCHAR) );
|
|
|
|
pStart += Length;
|
|
|
|
while ( pStart <= pEnd && *pStart == 32 )
|
|
pStart++;
|
|
|
|
ScreenX = LeftMargin;
|
|
ScreenY++;
|
|
}
|
|
ScreenY--;
|
|
|
|
ScreenX += Length;
|
|
|
|
if ( ScreenY > ScreenBottom ) {
|
|
ScreenY = ScreenBottom;
|
|
}
|
|
}
|
|
|
|
// If the copy buffer was allocated, free it.
|
|
if ( PrintBuf != NULL ) {
|
|
OscHeapFree( (PVOID)PrintBuf );
|
|
}
|
|
}
|
|
|
|
// **************************************************************************
|
|
//
|
|
// Lex section
|
|
//
|
|
// **************************************************************************
|
|
|
|
//
|
|
// Token list for screen parser
|
|
//
|
|
enum TOKENS {
|
|
TOKEN_ENDTAG = 0,
|
|
TOKEN_QUOTE,
|
|
TOKEN_HTML,
|
|
TOKEN_ENDHTML,
|
|
TOKEN_META,
|
|
TOKEN_SERVER,
|
|
TOKEN_KEY,
|
|
TOKEN_ENTER,
|
|
TOKEN_ESC,
|
|
TOKEN_F1,
|
|
TOKEN_F3,
|
|
TOKEN_HREF,
|
|
TOKEN_TITLE,
|
|
TOKEN_ENDTITLE,
|
|
TOKEN_FOOTER,
|
|
TOKEN_ENDFOOTER,
|
|
TOKEN_BODY,
|
|
TOKEN_ENDBODY,
|
|
TOKEN_PRE,
|
|
TOKEN_ENDPRE,
|
|
TOKEN_FORM,
|
|
TOKEN_ENDFORM,
|
|
TOKEN_ACTION,
|
|
TOKEN_INPUT,
|
|
TOKEN_NAME,
|
|
TOKEN_INPUTTYPE,
|
|
TOKEN_VALUE,
|
|
TOKEN_SIZE,
|
|
TOKEN_TIP,
|
|
TOKEN_MAXLENGTH,
|
|
TOKEN_ENCODE,
|
|
TOKEN_SELECT,
|
|
TOKEN_MULTIPLE,
|
|
TOKEN_NOAUTO,
|
|
TOKEN_ENDSELECT,
|
|
TOKEN_OPTION,
|
|
TOKEN_SELECTED,
|
|
TOKEN_HELP,
|
|
TOKEN_BREAK,
|
|
TOKEN_BOLD,
|
|
TOKEN_ENDBOLD,
|
|
TOKEN_FLASH,
|
|
TOKEN_ENDFLASH,
|
|
TOKEN_LEFT,
|
|
TOKEN_RIGHT,
|
|
TOKEN_TIPAREA,
|
|
TOKEN_PARAGRAPH,
|
|
TOKEN_ENDPARA,
|
|
#if defined(PLEASE_WAIT)
|
|
TOKEN_WAITMSG,
|
|
#endif
|
|
TOKEN_INVALID, // end of parsable tokens
|
|
TOKEN_TEXT,
|
|
TOKEN_START,
|
|
TOKEN_EOF, // End of file
|
|
};
|
|
|
|
static struct {
|
|
PCHAR name;
|
|
int length;
|
|
} Tags[] = {
|
|
{ ">", 1 },
|
|
{ "\"", 1 },
|
|
{ "<OSCML", 0 },
|
|
{ "</OSCML>", 0 },
|
|
{ "<META", 0 },
|
|
{ "SERVER", 0 },
|
|
{ "KEY=", 0 },
|
|
{ "ENTER", 0 },
|
|
{ "ESC", 0 },
|
|
{ "F1", 0 },
|
|
{ "F3", 0 },
|
|
{ "HREF=", 0 },
|
|
{ "<TITLE", 0 },
|
|
{ "</TITLE>", 0 },
|
|
{ "<FOOTER", 0 },
|
|
{ "</FOOTER>", 0 },
|
|
{ "<BODY", 0 },
|
|
{ "</BODY>", 0 },
|
|
{ "<PRE", 0 },
|
|
{ "</PRE>", 0 },
|
|
{ "<FORM", 0 },
|
|
{ "</FORM>", 0 },
|
|
{ "ACTION=", 0 },
|
|
{ "<INPUT", 0 },
|
|
{ "NAME=", 0 },
|
|
{ "TYPE=", 0 },
|
|
{ "VALUE=", 0 },
|
|
{ "SIZE=", 0 },
|
|
{ "TIP=", 0 },
|
|
{ "MAXLENGTH=", 0 },
|
|
{ "ENCODE=", 0 },
|
|
{ "<SELECT", 0 },
|
|
{ "MULTIPLE", 0 },
|
|
{ "NOAUTO", 0 },
|
|
{ "</SELECT>", 0 },
|
|
{ "<OPTION", 0 },
|
|
{ "SELECTED", 0 },
|
|
{ "HELP=", 0 },
|
|
{ "<BR", 0 },
|
|
{ "<BOLD", 0 },
|
|
{ "</BOLD", 0 },
|
|
{ "<FLASH", 0 },
|
|
{ "</FLASH", 0 },
|
|
{ "LEFT=", 0 },
|
|
{ "RIGHT=", 0 },
|
|
{ "<TIPAREA", 0 },
|
|
{ "<P", 0 },
|
|
{ "</P", 0 },
|
|
#if defined(PLEASE_WAIT)
|
|
{ "WAITMSG=", 0 },
|
|
#endif
|
|
{ NULL, 0 }, // end of parsable tokens
|
|
{ "[TEXT]", 0 },
|
|
{ "[START]", 0 },
|
|
{ "[EOF]", 0 }
|
|
};
|
|
|
|
//
|
|
// Lexstrcmpni( )
|
|
//
|
|
// Impliments strcmpni( ) for the Lexer.
|
|
//
|
|
int
|
|
Lexstrcmpni(
|
|
IN PCHAR pstr1,
|
|
IN PCHAR pstr2,
|
|
IN int iLength
|
|
)
|
|
{
|
|
while ( iLength && *pstr1 && *pstr2 )
|
|
{
|
|
CHAR ch1 = *pstr1;
|
|
CHAR ch2 = *pstr2;
|
|
|
|
if ( islower( ch1 ) )
|
|
{
|
|
ch1 = (CHAR)toupper(ch1);
|
|
}
|
|
|
|
if ( islower( ch2 ) )
|
|
{
|
|
ch2 = (CHAR)toupper(ch2);
|
|
}
|
|
|
|
if ( ch1 < ch2 )
|
|
return -1;
|
|
|
|
if ( ch1 > ch2 )
|
|
return 1;
|
|
|
|
pstr1++;
|
|
pstr2++;
|
|
iLength--;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// ReplaceSpecialCharacters( &psz );
|
|
//
|
|
void
|
|
ReplaceSpecialCharacters(
|
|
IN PCHAR psz)
|
|
{
|
|
TraceFunc( "ReplaceSpecialCharacters( )\n" );
|
|
|
|
if ( Lexstrcmpni( psz, "&NBSP", 5 ) == 0 ) {
|
|
*psz = CHAR_NBSP; // replace
|
|
memmove( psz + 1, psz + 5, strlen(psz) - 4 ); // shift
|
|
}
|
|
}
|
|
|
|
|
|
#if DBG
|
|
// #define LEX_SPEW
|
|
#endif
|
|
|
|
//
|
|
// Lex( )
|
|
//
|
|
// Parses the screen data moving the "InputString" pointer forward and
|
|
// returns the token for the text parsed. Spaces are ignored. Illegal
|
|
// characters are removed from the screen data. CRs are turned into
|
|
// spaces.
|
|
//
|
|
enum TOKENS
|
|
Lex(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
enum TOKENS Tag = TOKEN_TEXT;
|
|
PCHAR psz = *InputString;
|
|
int iCounter;
|
|
|
|
#if defined(LEX_SPEW) && defined(_TRACE_FUNC_)
|
|
TraceFunc( "Lex( " );
|
|
DPRINT( OSC, ("InputString = 0x%08x )\n", *InputString) );
|
|
#endif _TRACE_FUNC_
|
|
|
|
// skip spaces and control characters
|
|
if ( PreformattedMode == FALSE )
|
|
{
|
|
while ( *psz && *psz <= L' ' )
|
|
{
|
|
if (( *psz != 32 && *psz != '\n' )
|
|
|| ( psz != *InputString && (*(psz-1)) == 32 )) {
|
|
// remove any CR or LFs and any bogus characters
|
|
// also remove duplicate spaces in cases like:
|
|
//
|
|
// This is some text \n\r
|
|
// and more text.
|
|
//
|
|
// If we left it alone it would be printed:
|
|
//
|
|
// This is some text and more text.
|
|
//
|
|
memmove( psz, psz + 1, strlen(psz) );
|
|
} else {
|
|
*psz = 32;
|
|
psz++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( *psz == '&' ) {
|
|
ReplaceSpecialCharacters( psz );
|
|
}
|
|
|
|
if ( *psz ) {
|
|
for ( iCounter = 0; Tags[iCounter].name; iCounter++ )
|
|
{
|
|
if ( !Tags[iCounter].length ) {
|
|
Tags[iCounter].length = strlen( Tags[iCounter].name );
|
|
}
|
|
|
|
if ( Lexstrcmpni( psz, Tags[iCounter].name, Tags[iCounter].length ) == 0 ) {
|
|
psz += Tags[iCounter].length;
|
|
Tag = iCounter;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( Tag == TOKEN_TEXT )
|
|
psz++;
|
|
} else {
|
|
Tag = TOKEN_EOF;
|
|
}
|
|
|
|
#ifdef LEX_SPEW
|
|
{
|
|
CHAR tmp = *psz;
|
|
*psz = '\0';
|
|
DPRINT( OSC, ("[Lex] Parsed String: '%s' Result: %u - '%s'\n", *InputString, Tag, Tags[Tag].name) );
|
|
*psz = tmp;
|
|
}
|
|
#endif
|
|
|
|
*InputString = psz;
|
|
|
|
return Tag;
|
|
}
|
|
|
|
//
|
|
// GetString( )
|
|
//
|
|
// Finds and copies a string value from the screen data.
|
|
//
|
|
PCHAR
|
|
GetString(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
CHAR StopChar = 32;
|
|
PCHAR ReturnString = NULL;
|
|
PCHAR pszBegin = *InputString;
|
|
PCHAR pszEnd;
|
|
UINT Length;
|
|
CHAR tmp;
|
|
|
|
TraceFunc( "GetString( )\n" );
|
|
|
|
if ( !pszBegin )
|
|
goto e0;
|
|
|
|
// skip spaces
|
|
while ( *pszBegin == 32 )
|
|
pszBegin++;
|
|
|
|
// Check for quoted string
|
|
if ( *pszBegin == '\"' ) {
|
|
// find the end quote
|
|
pszBegin++;
|
|
pszEnd = strchr( pszBegin, '\"' );
|
|
|
|
} else {
|
|
// look for a break (space) or end token (">")
|
|
PCHAR pszSpace = strchr( pszBegin, ' ' );
|
|
PCHAR pszEndToken = strchr( pszBegin, '>' );
|
|
|
|
if ( !pszSpace ) {
|
|
pszEnd = pszEndToken;
|
|
} else if ( !pszEndToken ) {
|
|
pszEnd = pszSpace;
|
|
} else if ( pszEndToken < pszSpace ) {
|
|
pszEnd = pszEndToken;
|
|
} else {
|
|
pszEnd = pszSpace;
|
|
}
|
|
}
|
|
|
|
if ( !pszEnd )
|
|
goto e0;
|
|
|
|
tmp = *pszEnd; // save
|
|
*pszEnd = '\0'; // terminate
|
|
|
|
Length = strlen( pszBegin ) + 1;
|
|
ReturnString = OscHeapAlloc( Length );
|
|
if ( ReturnString ) {
|
|
strcpy( ReturnString, pszBegin );
|
|
}
|
|
*pszEnd = tmp; // restore
|
|
|
|
DPRINT( OSC, ("[String] %s<-\n", ReturnString) );
|
|
|
|
*InputString = pszEnd;
|
|
e0:
|
|
return ReturnString;
|
|
}
|
|
|
|
// **************************************************************************
|
|
//
|
|
// Parsing States Section
|
|
//
|
|
// **************************************************************************
|
|
|
|
//
|
|
// TitleTagState( )
|
|
//
|
|
enum TOKENS
|
|
TitleTagState(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
enum TOKENS Tag = TOKEN_START;
|
|
PCHAR PageTitle = *InputString;
|
|
|
|
TraceFunc( "TitleTagState( )\n" );
|
|
|
|
// ignore tag arguments
|
|
for( ; Tag != TOKEN_EOF && Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) );
|
|
|
|
PreformattedMode = TRUE;
|
|
|
|
while ( Tag != TOKEN_EOF )
|
|
{
|
|
switch (Tag)
|
|
{
|
|
case TOKEN_EOF:
|
|
// something went wrong, assume all this is text
|
|
*InputString = PageTitle;
|
|
PreformattedMode = FALSE;
|
|
return TOKEN_TEXT;
|
|
|
|
case TOKEN_ENDTAG:
|
|
PageTitle = *InputString;
|
|
break; // ignore
|
|
|
|
case TOKEN_ENDTITLE:
|
|
{
|
|
PCHAR psz = *InputString;
|
|
CHAR tmp;
|
|
|
|
psz -= Tags[Tag].length;
|
|
|
|
tmp = *psz;
|
|
*psz = L'\0';
|
|
|
|
BlpSendEscapeReverse(ScreenAttributes);
|
|
BlpPositionCursor( 1, 1 );
|
|
|
|
#ifdef _IN_OSDISP_
|
|
PRINT( SpaceString, sizeof(SpaceString) - sizeof(TCHAR) );
|
|
#else
|
|
PRINT( SpaceString, sizeof(SpaceString) );
|
|
#endif
|
|
|
|
if ( PageTitle ) {
|
|
BlpPositionCursor( 1, 1 );
|
|
DPRINT( OSC, ("[Title] '%s'\n", PageTitle) );
|
|
#ifdef UNICODE
|
|
{
|
|
ULONG i;
|
|
WCHAR wc;
|
|
for (i = 0; i < strlen(PageTitle) ; i++) {
|
|
wc = (WCHAR)PageTitle[i];
|
|
PRINT( &wc, sizeof(WCHAR));
|
|
}
|
|
}
|
|
#else
|
|
PRINTL( PageTitle );
|
|
#endif
|
|
}
|
|
|
|
BlpSendEscape(ScreenAttributes);
|
|
*psz = tmp;
|
|
PreformattedMode = FALSE;
|
|
return Tag; //exit state
|
|
}
|
|
break;
|
|
}
|
|
Tag = Lex( InputString );
|
|
}
|
|
|
|
PreformattedMode = FALSE;
|
|
return Tag;
|
|
}
|
|
|
|
//
|
|
// FooterTagState( )
|
|
//
|
|
enum TOKENS
|
|
FooterTagState(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
enum TOKENS Tag = TOKEN_START;
|
|
PCHAR PageFooter = *InputString;
|
|
|
|
TraceFunc( "FooterTagState( )\n" );
|
|
|
|
// ignore tag arguments
|
|
for( ; Tag != TOKEN_EOF && Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) );
|
|
|
|
PreformattedMode = TRUE;
|
|
|
|
while ( Tag != TOKEN_EOF )
|
|
{
|
|
switch (Tag)
|
|
{
|
|
case TOKEN_EOF:
|
|
// something went wrong, assume all this is text
|
|
*InputString = PageFooter;
|
|
PreformattedMode = FALSE;
|
|
return TOKEN_TEXT;
|
|
|
|
case TOKEN_ENDTAG:
|
|
PageFooter = *InputString;
|
|
break; // ignore
|
|
|
|
case TOKEN_ENDFOOTER:
|
|
{
|
|
PCHAR psz = *InputString;
|
|
CHAR tmp;
|
|
|
|
psz -= Tags[Tag].length;
|
|
|
|
tmp = *psz;
|
|
*psz = L'\0';
|
|
|
|
BlpSendEscapeReverse(ScreenAttributes);
|
|
BlpPositionCursor( 1, ScreenBottom );
|
|
|
|
#ifdef _IN_OSDISP_
|
|
PRINT( SpaceString, sizeof(SpaceString) - sizeof(TCHAR) );
|
|
#else
|
|
//
|
|
// if we're writing to a terminal, we don't want to write into the lower
|
|
// right corner as this would make us scroll.
|
|
//
|
|
PRINT( SpaceString, BlTerminalConnected
|
|
? (sizeof(SpaceString) - sizeof(TCHAR))
|
|
: sizeof(SpaceString) );
|
|
#endif
|
|
|
|
if ( PageFooter ) {
|
|
ULONG iLen;
|
|
BlpPositionCursor( 1, ScreenBottom );
|
|
DPRINT( OSC, ("[Footer] '%s'\n", PageFooter) );
|
|
|
|
iLen = strlen(PageFooter);
|
|
if (iLen > 79) {
|
|
iLen = 79;
|
|
}
|
|
#ifdef UNICODE
|
|
{
|
|
ULONG i;
|
|
WCHAR wc;
|
|
for (i = 0; i < iLen ; i++) {
|
|
wc = (WCHAR)PageFooter[i];
|
|
PRINT( &wc, sizeof(WCHAR));
|
|
}
|
|
}
|
|
#else
|
|
PRINT( PageFooter, iLen );
|
|
#endif
|
|
}
|
|
|
|
BlpSendEscape(ScreenAttributes);
|
|
*psz = tmp;
|
|
PreformattedMode = FALSE;
|
|
return Tag; //exit state
|
|
}
|
|
break;
|
|
}
|
|
Tag = Lex( InputString );
|
|
}
|
|
|
|
PreformattedMode = FALSE;
|
|
return Tag;
|
|
}
|
|
|
|
//
|
|
// InputTagState( )
|
|
//
|
|
enum TOKENS
|
|
InputTagState(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
enum TOKENS Tag = TOKEN_INVALID;
|
|
LPINPUTSTRUCT Input;
|
|
|
|
TraceFunc( "InputTagState( )\n" );
|
|
|
|
Input = (LPINPUTSTRUCT) OscHeapAlloc( sizeof(INPUTSTRUCT) );
|
|
if ( !Input )
|
|
{
|
|
// get tag arguments
|
|
for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) );
|
|
return TOKEN_INVALID;
|
|
}
|
|
|
|
RtlZeroMemory( Input, sizeof(INPUTSTRUCT) );
|
|
Input->Type |= CT_TEXT;
|
|
Input->Encoding = ET_NONE;
|
|
Input->X = ScreenX;
|
|
Input->Y = ScreenY;
|
|
|
|
// get tag arguments
|
|
for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
|
|
{
|
|
switch( Tag )
|
|
{
|
|
case TOKEN_NAME:
|
|
Input->Name = GetString( InputString );
|
|
if ( Input->Name )
|
|
DPRINT( OSC, ("[Input Name] %s\n", Input->Name) );
|
|
break;
|
|
|
|
case TOKEN_VALUE:
|
|
Input->Value = GetString( InputString );
|
|
if ( Input->Value )
|
|
DPRINT( OSC, ("[Input Value] %s\n", Input->Value) );
|
|
break;
|
|
|
|
case TOKEN_INPUTTYPE:
|
|
{
|
|
PCHAR pType = GetString( InputString );
|
|
if ( !pType )
|
|
break;
|
|
if ( Lexstrcmpni( pType, "PASSWORD", 8 ) == 0 ) {
|
|
Input->Type = CT_PASSWORD;
|
|
DPRINT( OSC, ("[Input Type] PASSWORD\n") );
|
|
} else if ( Lexstrcmpni( pType, "RESET", 5 ) == 0 ) {
|
|
Input->Type = CT_RESET;
|
|
DPRINT( OSC, ("[Input Type] RESET\n") );
|
|
} else if ( Lexstrcmpni( pType, "TEXT", 4 ) == 0 ) {
|
|
Input->Type = CT_TEXT;
|
|
DPRINT( OSC, ("[Input Type] TEXT\n") );
|
|
} else if ( Lexstrcmpni( pType, "LOCAL", 5 ) == 0 ) {
|
|
DPRINT( OSC, ("[Input Type] LOCAL\n") );
|
|
Input->Type = CT_LOCAL;
|
|
if ( Lexstrcmpni( pType + 5, "PASSWORD", 8 ) == 0 ) {
|
|
Input->Type |= CT_PASSWORD;
|
|
DPRINT( OSC, ("[Input Type] PASSWORD\n") );
|
|
} else if ( Lexstrcmpni( pType + 5, "RESET", 5 ) == 0 ) {
|
|
Input->Type |= CT_RESET;
|
|
DPRINT( OSC, ("[Input Type] RESET\n") );
|
|
} else if ( Lexstrcmpni( pType + 5, "TEXT", 4 ) == 0 ) {
|
|
Input->Type |= CT_TEXT;
|
|
DPRINT( OSC, ("[Input Type] TEXT\n") );
|
|
}
|
|
} else if ( Lexstrcmpni( pType, "VARIABLE", 8 ) == 0) {
|
|
Input->Type = CT_VARIABLE;
|
|
DPRINT( OSC, ("[Input Type] VARIABLE\n") );
|
|
}
|
|
|
|
OscHeapFree( pType );
|
|
}
|
|
break;
|
|
|
|
case TOKEN_SIZE:
|
|
{
|
|
PCHAR psz = GetString( InputString );
|
|
if ( psz ) {
|
|
PCHAR pszOld = psz; // save because GetInteger modifies
|
|
Input->Size = GetInteger( &psz );
|
|
OscHeapFree( pszOld );
|
|
DPRINT( OSC, ("[Input Size] %u\n", Input->Size) );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TOKEN_MAXLENGTH:
|
|
{
|
|
PCHAR psz = GetString( InputString );
|
|
|
|
if ( psz ) {
|
|
PUCHAR pTmpSz = psz;
|
|
|
|
Input->MaxLength = GetInteger( &pTmpSz );
|
|
|
|
if ( Input->MaxLength > MAX_INPUT_BUFFER_LENGTH - 1 ) {
|
|
Input->MaxLength = MAX_INPUT_BUFFER_LENGTH - 1;
|
|
}
|
|
OscHeapFree( psz );
|
|
DPRINT( OSC, ("[Input MaxLength] %u\n", Input->MaxLength) );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TOKEN_ENCODE:
|
|
{
|
|
PCHAR pType = GetString( InputString );
|
|
if ( !pType )
|
|
break;
|
|
if ( Lexstrcmpni( pType, "YES", 3 ) == 0 ) {
|
|
Input->Encoding = ET_OWF;
|
|
DPRINT( OSC, ("[Encoding Type] OWF\n") );
|
|
}
|
|
OscHeapFree( pType );
|
|
}
|
|
break;
|
|
|
|
case TOKEN_EOF:
|
|
return Tag;
|
|
}
|
|
}
|
|
|
|
// add the control to the list of controls
|
|
Input->Next = ScreenControls;
|
|
ScreenControls = Input;
|
|
|
|
if ( Input->Size + BRACKETS > RightMargin - ScreenX ) {
|
|
Input->Size = 0; // too big, so auto figure
|
|
}
|
|
|
|
// adjust screen coordinates
|
|
if ( !Input->Size && Input->MaxLength ) {
|
|
// figure out how much is left of the line, choose the smaller
|
|
Input->Size = ( (RightMargin - ScreenX) - BRACKETS < Input->MaxLength ?
|
|
(RightMargin - ScreenX) - BRACKETS : Input->MaxLength );
|
|
} else if ( !Input->Size ) {
|
|
// assume the input is going to take the whole line
|
|
Input->Size = (RightMargin - ScreenX) - BRACKETS;
|
|
}
|
|
|
|
if ( Input->Size > Input->MaxLength ) {
|
|
Input->Size = Input->MaxLength;
|
|
}
|
|
|
|
if ((Input->Type & CT_VARIABLE) == 0) {
|
|
ScreenX += Input->Size + BRACKETS + 1;
|
|
}
|
|
|
|
|
|
if ( ScreenX >= RightMargin ) {
|
|
ScreenX = LeftMargin;
|
|
ScreenY++;
|
|
}
|
|
|
|
if ( ScreenY > ScreenBottom )
|
|
ScreenY = ScreenBottom;
|
|
|
|
// display any predefined values
|
|
if ( Input->Value ) {
|
|
int Length = strlen(Input->Value);
|
|
if ((Input->Type & CT_VARIABLE) == 0) {
|
|
if ( Length > Input->Size ) {
|
|
Length = Input->Size;
|
|
}
|
|
if (Input->Type & CT_PASSWORD) {
|
|
int i;
|
|
BlpPositionCursor( Input->X + 2, Input->Y );
|
|
for( i = 0; i < Length; i ++ )
|
|
{
|
|
PRINT( TEXT("*"), 1*sizeof(TCHAR) );
|
|
}
|
|
} else {
|
|
BlpPositionCursor( Input->X + 2, Input->Y );
|
|
#ifdef UNICODE
|
|
{
|
|
int i;
|
|
WCHAR wc;
|
|
for (i = 0; i< Length; i++) {
|
|
wc = (WCHAR)(Input->Value)[i];
|
|
PRINT( &wc, 1*sizeof(WCHAR));
|
|
}
|
|
}
|
|
#else
|
|
PRINT( Input->Value, Length );
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
return Tag;
|
|
}
|
|
|
|
//
|
|
// OptionTagState( )
|
|
//
|
|
enum TOKENS
|
|
OptionTagState(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
enum TOKENS Tag = TOKEN_INVALID;
|
|
LPOPTIONSTRUCT Option;
|
|
PCHAR pszBegin, pszEnd;
|
|
ULONG Length;
|
|
|
|
TraceFunc( "OptionTagState( )\n" );
|
|
|
|
Option = (LPOPTIONSTRUCT) OscHeapAlloc( sizeof(OPTIONSTRUCT) );
|
|
if ( !Option )
|
|
{
|
|
// get tag arguments
|
|
for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) );
|
|
return TOKEN_INVALID;
|
|
}
|
|
|
|
RtlZeroMemory( Option, sizeof(OPTIONSTRUCT) );
|
|
Option->Type |= CT_OPTION;
|
|
|
|
// get tag arguments
|
|
for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
|
|
{
|
|
switch( Tag )
|
|
{
|
|
case TOKEN_VALUE:
|
|
Option->Value = GetString( InputString );
|
|
if ( Option->Value )
|
|
DPRINT( OSC, ("[Options Value] %s\n", Option->Value) );
|
|
break;
|
|
|
|
case TOKEN_SELECTED:
|
|
DPRINT( OSC, ("[Option] SELECTED\n") );
|
|
Option->Flags = OF_SELECTED;
|
|
break;
|
|
|
|
case TOKEN_TIP:
|
|
Option->Tip = GetString( InputString );
|
|
if ( Option->Tip ) {
|
|
PCHAR psz = Option->Tip;
|
|
Option->EndTip = &Option->Tip[strlen(Option->Tip)];
|
|
// strip CRs and LFs from tip
|
|
while ( psz < Option->EndTip )
|
|
{
|
|
if ( (*psz == '\r') ||
|
|
((*psz < 32) && ((psz == Option->Tip) || (*(psz-1) == ' '))) )
|
|
{ // remove control codes that follows spaces and all CRs
|
|
memmove( psz, psz+1, strlen(psz) );
|
|
Option->EndTip--;
|
|
}
|
|
else
|
|
{
|
|
if ( *psz < 32 )
|
|
{ // turn control codes into spaces
|
|
*psz = 32;
|
|
}
|
|
psz++;
|
|
}
|
|
}
|
|
DPRINT( OSC, ("[Option Tip] %s\n", Option->Tip) );
|
|
}
|
|
break;
|
|
|
|
case TOKEN_EOF:
|
|
return Tag;
|
|
}
|
|
}
|
|
|
|
// get the option title - at this point Tag == TOKEN_ENDTAG
|
|
pszBegin = *InputString;
|
|
for(Tag = Lex( InputString ) ; Tag != TOKEN_EOF; Tag = Lex( InputString ) )
|
|
{
|
|
BOOLEAN ExitLoop = FALSE;
|
|
switch( Tag )
|
|
{
|
|
case TOKEN_HTML:
|
|
case TOKEN_ENDHTML:
|
|
case TOKEN_META:
|
|
case TOKEN_TITLE:
|
|
case TOKEN_ENDTITLE:
|
|
case TOKEN_FOOTER:
|
|
case TOKEN_ENDFOOTER:
|
|
case TOKEN_BODY:
|
|
case TOKEN_ENDBODY:
|
|
case TOKEN_PRE:
|
|
case TOKEN_ENDPRE:
|
|
case TOKEN_FORM:
|
|
case TOKEN_ENDFORM:
|
|
case TOKEN_INPUT:
|
|
case TOKEN_SELECT:
|
|
case TOKEN_ENDSELECT:
|
|
case TOKEN_OPTION:
|
|
case TOKEN_BREAK:
|
|
case TOKEN_TIPAREA:
|
|
case TOKEN_PARAGRAPH:
|
|
case TOKEN_ENDPARA:
|
|
case TOKEN_INVALID:
|
|
ExitLoop = TRUE;
|
|
break;
|
|
}
|
|
|
|
if ( ExitLoop == TRUE )
|
|
break;
|
|
}
|
|
pszEnd = (*InputString) - Tags[Tag].length;
|
|
|
|
// try to take the crud and extra spaces off the end
|
|
while ( pszEnd > pszBegin && *pszEnd <= 32 )
|
|
pszEnd--;
|
|
|
|
if ( pszEnd == pszBegin ) {
|
|
pszEnd = (*InputString) - Tags[Tag].length;
|
|
}
|
|
|
|
Length = PtrToUint((PVOID)(pszEnd - pszBegin));
|
|
Option->Displayed = OscHeapAlloc( Length + 1 );
|
|
if ( Option->Displayed ) {
|
|
CHAR tmp = *pszEnd; // save
|
|
*pszEnd = '\0'; // terminate
|
|
strcpy( Option->Displayed, pszBegin );
|
|
*pszEnd = tmp; // restore
|
|
DPRINT( OSC, ("[Option Name] %s\n", Option->Displayed) );
|
|
|
|
// add the control to the list of controls
|
|
Option->Next = ScreenControls;
|
|
ScreenControls = Option;
|
|
|
|
} else {
|
|
|
|
// remove it since there is nothing to display
|
|
if ( Option->Tip )
|
|
OscHeapFree( Option->Tip );
|
|
if ( Option->Value )
|
|
OscHeapFree( Option->Value );
|
|
OscHeapFree( (void *)Option );
|
|
}
|
|
return Tag;
|
|
}
|
|
|
|
//
|
|
// SelectTagState( )
|
|
//
|
|
enum TOKENS
|
|
SelectTagState(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
enum TOKENS Tag = TOKEN_INVALID;
|
|
LPSELECTSTRUCT Select;
|
|
|
|
TraceFunc( "SelectTagState( )\n" );
|
|
|
|
Select = (LPSELECTSTRUCT) OscHeapAlloc( sizeof(SELECTSTRUCT) );
|
|
if ( !Select )
|
|
{
|
|
// get tag arguments
|
|
for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) );
|
|
return TOKEN_INVALID;
|
|
}
|
|
|
|
RtlZeroMemory( Select, sizeof(SELECTSTRUCT) );
|
|
Select->Type |= CT_SELECT;
|
|
Select->X = ScreenX;
|
|
Select->Y = ScreenY;
|
|
Select->Size = 1;
|
|
Select->AutoSelect = TRUE;
|
|
|
|
// get tag arguments
|
|
for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
|
|
{
|
|
switch( Tag )
|
|
{
|
|
case TOKEN_NAME:
|
|
Select->Name = GetString( InputString );
|
|
if ( Select->Name )
|
|
DPRINT( OSC, ("[Select Name] %s\n", Select->Name) );
|
|
break;
|
|
|
|
case TOKEN_MULTIPLE:
|
|
DPRINT( OSC, ("[Select] MULTIPLE\n") );
|
|
Select->Flags = OF_MULTIPLE;
|
|
break;
|
|
|
|
case TOKEN_NOAUTO:
|
|
DPRINT( OSC, ("[Select] NOAUTO\n") );
|
|
Select->AutoSelect = FALSE;
|
|
break;
|
|
|
|
case TOKEN_SIZE:
|
|
{
|
|
PCHAR psz = GetString( InputString );
|
|
if ( psz ) {
|
|
PCHAR pszOld = psz; // save because GetInteger modifies
|
|
Select->Size = GetInteger( &psz );
|
|
OscHeapFree( pszOld );
|
|
DPRINT( OSC, ("[Select Size] %u\n", Select->Size) );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case TOKEN_EOF:
|
|
return Tag;
|
|
}
|
|
}
|
|
|
|
// add the control to the list of controls
|
|
Select->Next = ScreenControls;
|
|
ScreenControls = Select;
|
|
|
|
while( Tag != TOKEN_ENDSELECT && Tag != TOKEN_EOF )
|
|
{
|
|
switch( Tag )
|
|
{
|
|
case TOKEN_OPTION:
|
|
{
|
|
LPOPTIONSTRUCT Option;
|
|
|
|
Tag = OptionTagState( InputString );
|
|
|
|
Option = ScreenControls;
|
|
if ( Option->Type & CT_OPTION ) {
|
|
if ( Option->Displayed ) {
|
|
int Length = strlen( Option->Displayed ) + 1;
|
|
if ( Select->Width < Length ) {
|
|
Select->Width = Length;
|
|
}
|
|
}
|
|
if ( Option->Flags == OF_SELECTED ) {
|
|
Select->CurrentSelection = Option;
|
|
if ( Select->Flags != OF_MULTIPLE )
|
|
{
|
|
Option->Flags = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
|
|
default:
|
|
Tag = Lex( InputString );
|
|
}
|
|
}
|
|
|
|
// adjust screen coordinates
|
|
ScreenY += Select->Size;
|
|
|
|
if ( ScreenY > ScreenBottom ) {
|
|
Select->Size -= ScreenY - ScreenBottom;
|
|
ScreenY = ScreenBottom;
|
|
}
|
|
return Tag;
|
|
}
|
|
|
|
//
|
|
// PreformattedPrint( )
|
|
//
|
|
void
|
|
PreformattedPrint(
|
|
IN PCHAR Start,
|
|
IN PCHAR End
|
|
)
|
|
{
|
|
#ifdef _TRACE_FUNC_
|
|
TraceFunc( "PreformattedPrint( " );
|
|
DPRINT( OSC, ("Start = 0x%08x, End = 0x%08x )\n", Start, End) );
|
|
#endif
|
|
|
|
BlpPositionCursor( ScreenX, ScreenY );
|
|
|
|
while ( Start < End )
|
|
{
|
|
int Length, OldLength;
|
|
|
|
while ( Start < End && (*Start == '\r' || *Start == '\n') )
|
|
{
|
|
if ( *Start == '\r' ) {
|
|
ScreenX = LeftMargin;
|
|
}
|
|
if ( *Start == '\n' ) {
|
|
ScreenY++;
|
|
if ( ScreenY > ScreenBottom ) {
|
|
ScreenY = ScreenBottom;
|
|
}
|
|
}
|
|
Start++;
|
|
}
|
|
|
|
Length = PtrToUint((PVOID)(End - Start));
|
|
if ( !Length )
|
|
continue; // nothing to print
|
|
|
|
// trunk if needed
|
|
if ( Length > RightMargin - ScreenX ) {
|
|
|
|
Length = RightMargin - ScreenX;
|
|
}
|
|
|
|
// try to find a "break" character
|
|
OldLength = Length;
|
|
while ( Length && Start[Length] != '\r' && Start[Length] != '\n' )
|
|
Length--;
|
|
|
|
// If we can't "break" it, just dump one line's worth
|
|
if ( !Length ) {
|
|
DPRINT( OSC, ("[FormattedPrint, Length == 0, Dumping a lines worth]\n") );
|
|
Length = OldLength;
|
|
}
|
|
#if DBG
|
|
{
|
|
CHAR tmp = Start[Length];
|
|
Start[Length] = 0;
|
|
DPRINT( OSC, ("[FormattedPrint, Length=%u] '%s'\n", Length, Start) );
|
|
Start[Length] = tmp;
|
|
}
|
|
#endif
|
|
BlpPositionCursor( ScreenX, ScreenY );
|
|
#ifdef UNICODE
|
|
{
|
|
int i;
|
|
WCHAR wc;
|
|
for (i = 0; i < Length; i++) {
|
|
wc = (WCHAR) Start[i];
|
|
PRINT( &wc, 1*sizeof(WCHAR));
|
|
}
|
|
}
|
|
#else
|
|
PRINT( Start, Length );
|
|
#endif
|
|
|
|
ScreenX += Length;
|
|
|
|
while ( Start < End && *Start != '\r' && *Start != '\n' )
|
|
Start++;
|
|
}
|
|
}
|
|
//
|
|
// PreTagState( )
|
|
//
|
|
enum TOKENS
|
|
PreTagState(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
enum TOKENS Tag = TOKEN_START;
|
|
PCHAR psz = *InputString;
|
|
|
|
TraceFunc( "PreTagState( )\n" );
|
|
|
|
// get tag arguments
|
|
for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
|
|
{
|
|
switch( Tag )
|
|
{
|
|
case TOKEN_LEFT:
|
|
psz = *InputString;
|
|
// skip any spaces
|
|
while( *psz && *psz == 32 )
|
|
psz++;
|
|
*InputString = psz;
|
|
LeftMargin = GetInteger( InputString );
|
|
DPRINT( OSC, ("[LeftMargin = %u]\n", LeftMargin) );
|
|
break;
|
|
|
|
case TOKEN_RIGHT:
|
|
psz = *InputString;
|
|
// skip any spaces
|
|
while( *psz && *psz == 32 )
|
|
psz++;
|
|
*InputString = psz;
|
|
RightMargin = GetInteger( InputString );
|
|
DPRINT( OSC, ("[RightMargin = %u]\n", RightMargin) );
|
|
break;
|
|
|
|
case TOKEN_EOF:
|
|
return Tag;
|
|
}
|
|
}
|
|
|
|
if ( ScreenX >= RightMargin ) {
|
|
ScreenY++;
|
|
if ( ScreenY > ScreenBottom ) {
|
|
ScreenY = ScreenBottom;
|
|
}
|
|
}
|
|
if ( ScreenX >= RightMargin || ScreenX < LeftMargin ) {
|
|
ScreenX = LeftMargin;
|
|
}
|
|
|
|
PreformattedMode = TRUE;
|
|
psz = *InputString;
|
|
while ( Tag != TOKEN_EOF )
|
|
{
|
|
switch (Tag)
|
|
{
|
|
case TOKEN_ENDPRE:
|
|
case TOKEN_ENDHTML:
|
|
case TOKEN_ENDBODY:
|
|
PreformattedPrint( psz, (*InputString) - Tags[Tag].length );
|
|
PreformattedMode = FALSE;
|
|
return Tag; // exit state
|
|
|
|
// just print everything else
|
|
default:
|
|
PreformattedPrint( psz, *InputString );
|
|
psz = *InputString;
|
|
Tag = Lex( InputString );
|
|
break;
|
|
}
|
|
}
|
|
PreformattedMode = FALSE;
|
|
return Tag;
|
|
}
|
|
|
|
//
|
|
// TipAreaTagState( )
|
|
//
|
|
enum TOKENS
|
|
TipAreaTagState(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
enum TOKENS Tag = TOKEN_START;
|
|
PCHAR psz = *InputString;
|
|
|
|
TraceFunc( "TipAreaTagState( )\n" );
|
|
|
|
if ( !TipArea ) {
|
|
TipArea = (LPTIPAREA) OscHeapAlloc( sizeof(TIPAREA) );
|
|
if ( !TipArea )
|
|
{
|
|
// get tag arguments
|
|
for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) );
|
|
return TOKEN_INVALID;
|
|
}
|
|
}
|
|
|
|
TipArea->X = ScreenX;
|
|
TipArea->Y = ScreenY;
|
|
TipArea->LeftMargin = LeftMargin;
|
|
TipArea->RightMargin = RightMargin;
|
|
TipArea->Size = ScreenBottom - ScreenY;
|
|
|
|
// get tag arguments
|
|
for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
|
|
{
|
|
switch( Tag )
|
|
{
|
|
case TOKEN_LEFT:
|
|
psz = *InputString;
|
|
// skip any spaces
|
|
while( *psz && *psz == 32 )
|
|
psz++;
|
|
*InputString = psz;
|
|
TipArea->LeftMargin = GetInteger( InputString );
|
|
DPRINT( OSC, ("[TipArea LeftMargin = %u]\n", TipArea->LeftMargin) );
|
|
break;
|
|
|
|
case TOKEN_RIGHT:
|
|
psz = *InputString;
|
|
// skip any spaces
|
|
while( *psz && *psz == 32 )
|
|
psz++;
|
|
*InputString = psz;
|
|
TipArea->RightMargin = GetInteger( InputString );
|
|
DPRINT( OSC, ("[TipArea RightMargin = %u]\n", TipArea->RightMargin) );
|
|
break;
|
|
|
|
case TOKEN_SIZE:
|
|
psz = *InputString;
|
|
// skip any spaces
|
|
while( *psz && *psz == 32 )
|
|
psz++;
|
|
*InputString = psz;
|
|
TipArea->Size = GetInteger( InputString ) - 1;
|
|
if ( TipArea->Size < 1 ) {
|
|
TipArea->Size = 1;
|
|
}
|
|
DPRINT( OSC, ("[TipArea Size = %u]\n", TipArea->Size) );
|
|
ScreenY += TipArea->Size;
|
|
break;
|
|
|
|
case TOKEN_EOF:
|
|
// imcomplete statement - so don't have a tiparea.
|
|
TipArea = NULL;
|
|
return Tag;
|
|
}
|
|
}
|
|
|
|
if ( ScreenY > ScreenBottom ) {
|
|
ScreenY = ScreenBottom;
|
|
}
|
|
return Tag;
|
|
}
|
|
|
|
int ParaOldLeftMargin = 0;
|
|
int ParaOldRightMargin = 0;
|
|
|
|
//
|
|
// ParagraphTagState( )
|
|
//
|
|
enum TOKENS
|
|
ParagraphTagState(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
enum TOKENS Tag = TOKEN_START;
|
|
PCHAR psz;
|
|
|
|
TraceFunc( "ParagraphTagState( )\n" );
|
|
ParaOldLeftMargin = LeftMargin;
|
|
ParaOldRightMargin = RightMargin;
|
|
|
|
// get tag arguments
|
|
for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
|
|
{
|
|
switch( Tag )
|
|
{
|
|
case TOKEN_LEFT:
|
|
psz = *InputString;
|
|
// skip any spaces
|
|
while( *psz && *psz == 32 )
|
|
psz++;
|
|
*InputString = psz;
|
|
LeftMargin = GetInteger( InputString );
|
|
DPRINT( OSC, ("[LeftMargin = %u]\n", LeftMargin) );
|
|
break;
|
|
|
|
case TOKEN_RIGHT:
|
|
psz = *InputString;
|
|
// skip any spaces
|
|
while( *psz && *psz == 32 )
|
|
psz++;
|
|
*InputString = psz;
|
|
RightMargin = GetInteger( InputString );
|
|
DPRINT( OSC, ("[RightMargin = %u]\n", RightMargin) );
|
|
break;
|
|
|
|
case TOKEN_EOF:
|
|
return Tag;
|
|
}
|
|
}
|
|
|
|
// always simulate a <BR>
|
|
ScreenY++;
|
|
if ( ScreenY > ScreenBottom ) {
|
|
ScreenY = ScreenBottom;
|
|
}
|
|
ScreenX = LeftMargin;
|
|
return Tag;
|
|
}
|
|
|
|
//
|
|
// FormTagState( )
|
|
//
|
|
enum TOKENS
|
|
FormTagState(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
enum TOKENS Tag = TOKEN_START;
|
|
PCHAR psz;
|
|
|
|
TraceFunc( "FormTagState( )\n" );
|
|
// get tag arguments
|
|
for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
|
|
{
|
|
switch( Tag )
|
|
{
|
|
case TOKEN_ACTION:
|
|
if ( !EnterKey ) {
|
|
EnterKey = (LPKEY_RESPONSE) OscHeapAlloc( sizeof(KEY_RESPONSE) );
|
|
}
|
|
if ( !EnterKey )
|
|
break;
|
|
EnterKey->Action = ACTION_JUMP;
|
|
EnterKey->ScreenName = GetString( InputString );
|
|
if ( EnterKey->ScreenName )
|
|
DPRINT( OSC, ("[Key Enter Action: JUMP to '%s.OSC']\n", EnterKey->ScreenName) );
|
|
break;
|
|
|
|
case TOKEN_EOF:
|
|
return Tag;
|
|
}
|
|
}
|
|
|
|
psz = *InputString;
|
|
|
|
while ( Tag != TOKEN_EOF && Tag != TOKEN_ENDFORM )
|
|
{
|
|
switch (Tag)
|
|
{
|
|
default:
|
|
if ( !psz ) {
|
|
psz = *InputString;
|
|
}
|
|
Tag = Lex( InputString );
|
|
break;
|
|
|
|
case TOKEN_SELECT:
|
|
case TOKEN_INPUT:
|
|
case TOKEN_PRE:
|
|
case TOKEN_BOLD:
|
|
case TOKEN_FLASH:
|
|
case TOKEN_ENDFLASH:
|
|
case TOKEN_ENDBOLD:
|
|
case TOKEN_BREAK:
|
|
case TOKEN_ENDBODY:
|
|
case TOKEN_FORM:
|
|
case TOKEN_TIPAREA:
|
|
case TOKEN_EOF:
|
|
case TOKEN_PARAGRAPH:
|
|
case TOKEN_ENDPARA:
|
|
if ( psz ) {
|
|
BlpPrintString( psz, (*InputString) - Tags[Tag].length );
|
|
psz = NULL; // reset
|
|
}
|
|
|
|
switch( Tag )
|
|
{
|
|
case TOKEN_SELECT:
|
|
Tag = SelectTagState( InputString );
|
|
break;
|
|
|
|
case TOKEN_INPUT:
|
|
Tag = InputTagState( InputString );
|
|
break;
|
|
|
|
case TOKEN_EOF:
|
|
return Tag;
|
|
|
|
case TOKEN_PRE:
|
|
Tag = PreTagState( InputString );
|
|
break;
|
|
|
|
case TOKEN_BOLD:
|
|
BlpSendEscapeBold(ScreenAttributes);
|
|
DPRINT( OSC, ("[Bold]\n") );
|
|
Tag = Lex( InputString );
|
|
break;
|
|
|
|
case TOKEN_FLASH:
|
|
BlpSendEscapeFlash(ScreenAttributes);
|
|
DPRINT( OSC, ("[Flash]\n") );
|
|
Tag = Lex( InputString );
|
|
break;
|
|
|
|
case TOKEN_ENDFLASH:
|
|
case TOKEN_ENDBOLD:
|
|
BlpSendEscape(ScreenAttributes);
|
|
DPRINT( OSC, ("[Normal]\n") );
|
|
Tag = Lex( InputString );
|
|
break;
|
|
|
|
case TOKEN_FORM:
|
|
// ignore it
|
|
Tag = Lex( InputString );
|
|
break;
|
|
|
|
case TOKEN_BREAK:
|
|
ScreenX = LeftMargin;
|
|
ScreenY++;
|
|
if ( ScreenY > ScreenBottom ) {
|
|
ScreenY = ScreenBottom;
|
|
}
|
|
Tag = Lex( InputString );
|
|
break;
|
|
|
|
case TOKEN_TIPAREA:
|
|
Tag = TipAreaTagState( InputString );
|
|
break;
|
|
|
|
case TOKEN_PARAGRAPH:
|
|
Tag = ParagraphTagState( InputString );
|
|
break;
|
|
|
|
case TOKEN_ENDPARA:
|
|
LeftMargin = ParaOldLeftMargin;
|
|
RightMargin = ParaOldRightMargin;
|
|
// Make sure the boundaries are realistic
|
|
if ( LeftMargin < 1 ) {
|
|
LeftMargin = 1;
|
|
}
|
|
if ( RightMargin <= LeftMargin ) {
|
|
RightMargin = LeftMargin + 1;
|
|
}
|
|
if ( RightMargin < 1 ) {
|
|
RightMargin = 80;
|
|
}
|
|
// always simulate a <BR>
|
|
ScreenY++;
|
|
if ( ScreenY > ScreenBottom ) {
|
|
ScreenY = ScreenBottom;
|
|
}
|
|
ScreenX = LeftMargin;
|
|
Tag = Lex( InputString );
|
|
break;
|
|
|
|
case TOKEN_ENDBODY:
|
|
return Tag; // exit state
|
|
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return Tag;
|
|
}
|
|
|
|
//
|
|
// ImpliedBodyTagState( )
|
|
//
|
|
enum TOKENS
|
|
ImpliedBodyTagState(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
enum TOKENS Tag = TOKEN_START;
|
|
PCHAR psz = *InputString;
|
|
|
|
TraceFunc( "ImpliedBodyTagState( )\n" );
|
|
|
|
while ( TRUE )
|
|
{
|
|
// KB: All items in this switch statment must have Tag returned
|
|
// to them from a function call or must call Lex( ) to get
|
|
// the next Tag.
|
|
switch (Tag)
|
|
{
|
|
default:
|
|
if ( !psz ) {
|
|
psz = *InputString;
|
|
}
|
|
Tag = Lex( InputString );
|
|
break;
|
|
|
|
case TOKEN_PRE:
|
|
case TOKEN_BOLD:
|
|
case TOKEN_FLASH:
|
|
case TOKEN_ENDFLASH:
|
|
case TOKEN_ENDBOLD:
|
|
case TOKEN_BREAK:
|
|
case TOKEN_ENDBODY:
|
|
case TOKEN_FORM:
|
|
case TOKEN_TIPAREA:
|
|
case TOKEN_EOF:
|
|
case TOKEN_PARAGRAPH:
|
|
case TOKEN_ENDPARA:
|
|
if ( psz ) {
|
|
BlpPrintString( psz, (*InputString) - Tags[Tag].length );
|
|
psz = NULL; // reset
|
|
}
|
|
|
|
switch( Tag )
|
|
{
|
|
case TOKEN_EOF:
|
|
return Tag;
|
|
|
|
case TOKEN_PRE:
|
|
Tag = PreTagState( InputString );
|
|
break;
|
|
|
|
case TOKEN_BOLD:
|
|
BlpSendEscapeBold(ScreenAttributes);
|
|
DPRINT( OSC, ("[Bold]\n") );
|
|
Tag = Lex( InputString );
|
|
break;
|
|
|
|
case TOKEN_FLASH:
|
|
BlpSendEscapeFlash(ScreenAttributes);
|
|
DPRINT( OSC, ("[Flash]\n") );
|
|
Tag = Lex( InputString );
|
|
break;
|
|
|
|
case TOKEN_ENDFLASH:
|
|
case TOKEN_ENDBOLD:
|
|
BlpSendEscape(ScreenAttributes);
|
|
DPRINT( OSC, ("[Normal]\n") );
|
|
Tag = Lex( InputString );
|
|
break;
|
|
|
|
case TOKEN_FORM:
|
|
Tag = FormTagState( InputString );
|
|
break;
|
|
|
|
case TOKEN_BREAK:
|
|
ScreenX = LeftMargin;
|
|
ScreenY++;
|
|
if ( ScreenY > ScreenBottom ) {
|
|
ScreenY = ScreenBottom;
|
|
}
|
|
Tag = Lex( InputString );
|
|
break;
|
|
|
|
case TOKEN_TIPAREA:
|
|
Tag = TipAreaTagState( InputString );
|
|
break;
|
|
|
|
case TOKEN_PARAGRAPH:
|
|
Tag = ParagraphTagState( InputString );
|
|
break;
|
|
|
|
case TOKEN_ENDPARA:
|
|
LeftMargin = ParaOldLeftMargin;
|
|
RightMargin = ParaOldRightMargin;
|
|
// Make sure the boundaries are realistic
|
|
if ( LeftMargin < 1 ) {
|
|
LeftMargin = 1;
|
|
}
|
|
if ( RightMargin <= LeftMargin ) {
|
|
RightMargin = LeftMargin + 1;
|
|
}
|
|
if ( RightMargin < 1 ) {
|
|
RightMargin = 80;
|
|
}
|
|
// always simulate a <BR>
|
|
ScreenY++;
|
|
if ( ScreenY > ScreenBottom ) {
|
|
ScreenY = ScreenBottom;
|
|
}
|
|
ScreenX = LeftMargin;
|
|
Tag = Lex( InputString );
|
|
break;
|
|
|
|
case TOKEN_ENDBODY:
|
|
return Tag; // exit state
|
|
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return Tag;
|
|
}
|
|
|
|
//
|
|
// BodyTagState( )
|
|
//
|
|
enum TOKENS
|
|
BodyTagState(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
enum TOKENS Tag = TOKEN_START;
|
|
PCHAR psz;
|
|
|
|
TraceFunc( "BodyTagState( )\n" );
|
|
|
|
// get tag arguments
|
|
for( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
|
|
{
|
|
switch( Tag )
|
|
{
|
|
case TOKEN_LEFT:
|
|
psz = *InputString;
|
|
// skip any spaces
|
|
while( *psz && *psz == 32 )
|
|
psz++;
|
|
*InputString = psz;
|
|
LeftMargin = GetInteger( InputString );
|
|
DPRINT( OSC, ("[LeftMargin = %u]\n", LeftMargin) );
|
|
break;
|
|
|
|
case TOKEN_RIGHT:
|
|
psz = *InputString;
|
|
// skip any spaces
|
|
while( *psz && *psz == 32 )
|
|
psz++;
|
|
*InputString = psz;
|
|
RightMargin = GetInteger( InputString );
|
|
DPRINT( OSC, ("[RightMargin = %u]\n", RightMargin) );
|
|
break;
|
|
|
|
case TOKEN_EOF:
|
|
return Tag;
|
|
}
|
|
}
|
|
|
|
if ( ScreenX >= RightMargin ) {
|
|
ScreenY++;
|
|
if ( ScreenY > ScreenBottom ) {
|
|
ScreenY = ScreenBottom;
|
|
}
|
|
}
|
|
if ( ScreenX >= RightMargin || ScreenX < LeftMargin ) {
|
|
ScreenX = LeftMargin;
|
|
}
|
|
return ImpliedBodyTagState( InputString );
|
|
}
|
|
|
|
//
|
|
// KeyTagState( )
|
|
//
|
|
enum TOKENS
|
|
KeyTagState(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
enum TOKENS Tag = TOKEN_START;
|
|
LPKEY_RESPONSE Key = NULL;
|
|
PCHAR ScreenName = NULL;
|
|
|
|
TraceFunc( "KeyTagState( )\n" );
|
|
|
|
// get arguments
|
|
for ( ; Tag != TOKEN_ENDTAG ; Tag = Lex( InputString ) )
|
|
{
|
|
switch (Tag)
|
|
{
|
|
case TOKEN_ENTER:
|
|
DPRINT( OSC, ("[Key Enter]\n") );
|
|
EnterKey = (LPKEY_RESPONSE) OscHeapAlloc( sizeof(KEY_RESPONSE) );
|
|
if ( !EnterKey )
|
|
break;
|
|
Key = EnterKey;
|
|
Key->ScreenName = NULL;
|
|
Key->Action = ACTION_NOP;
|
|
break;
|
|
|
|
case TOKEN_F1:
|
|
DPRINT( OSC, ("[Key F1]\n") );
|
|
F1Key = (LPKEY_RESPONSE) OscHeapAlloc( sizeof(KEY_RESPONSE) );
|
|
if ( !F1Key )
|
|
break;
|
|
Key = F1Key;
|
|
Key->ScreenName = NULL;
|
|
Key->Action = ACTION_NOP;
|
|
break;
|
|
|
|
case TOKEN_F3:
|
|
DPRINT( OSC, ("[Key F3]\n") );
|
|
F3Key = (LPKEY_RESPONSE) OscHeapAlloc( sizeof(KEY_RESPONSE) );
|
|
if ( !F3Key )
|
|
break;
|
|
Key = F3Key;
|
|
Key->ScreenName = NULL;
|
|
Key->Action = ACTION_NOP;
|
|
break;
|
|
|
|
case TOKEN_ESC:
|
|
DPRINT( OSC, ("[Key Escape]\n") );
|
|
EscKey = (LPKEY_RESPONSE) OscHeapAlloc( sizeof(KEY_RESPONSE) );
|
|
if ( !EscKey )
|
|
break;
|
|
Key = EscKey;
|
|
Key->ScreenName = NULL;
|
|
Key->Action = ACTION_NOP;
|
|
break;
|
|
|
|
case TOKEN_HREF:
|
|
if ( Key ) {
|
|
Key->Action = ACTION_JUMP;
|
|
Key->ScreenName = GetString( InputString );
|
|
if ( Key->ScreenName )
|
|
DPRINT( OSC, ("[Key Action: JUMP to '%s.OSC']\n", Key->ScreenName) );
|
|
}
|
|
break;
|
|
|
|
case TOKEN_ACTION:
|
|
if ( Key ) {
|
|
PCHAR pAction = GetString( InputString );
|
|
if ( !pAction )
|
|
break;
|
|
if ( Lexstrcmpni( pAction, "REBOOT", 6 ) == 0 ) {
|
|
DPRINT( OSC, ("[Key Action: REBOOT]\n") );
|
|
Key->Action = ACTION_REBOOT;
|
|
} else {
|
|
DPRINT( OSC, ("[Key Action?] %s\n", pAction) );
|
|
}
|
|
OscHeapFree( pAction );
|
|
}
|
|
break;
|
|
|
|
case TOKEN_EOF:
|
|
return Tag;
|
|
}
|
|
}
|
|
return Tag;
|
|
}
|
|
|
|
//
|
|
// MetaTagState( )
|
|
//
|
|
enum TOKENS
|
|
MetaTagState(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
enum TOKENS Tag = TOKEN_START;
|
|
|
|
TraceFunc( "MetaTagState( )\n" );
|
|
// get tag arguments
|
|
while ( Tag != TOKEN_ENDTAG )
|
|
{
|
|
// KB: All items in this switch statment must have Tag returned
|
|
// to them from a function call or must call Lex( ) to get
|
|
// the next Tag.
|
|
switch (Tag)
|
|
{
|
|
case TOKEN_EOF:
|
|
return Tag;
|
|
|
|
case TOKEN_KEY:
|
|
Tag = KeyTagState( InputString );
|
|
break;
|
|
|
|
case TOKEN_SERVER:
|
|
DPRINT( OSC, ("[Server Meta - ignored]\n") );
|
|
// ignore server side METAs
|
|
while ( Tag != TOKEN_EOF && Tag != TOKEN_ENDTAG )
|
|
{
|
|
Tag = Lex( InputString );
|
|
}
|
|
break;
|
|
|
|
#if defined(PLEASE_WAIT)
|
|
case TOKEN_WAITMSG:
|
|
{
|
|
if ( PleaseWaitMsg )
|
|
{
|
|
OscHeapFree( PleaseWaitMsg );
|
|
}
|
|
|
|
PleaseWaitMsg = GetString( InputString );
|
|
if ( !PleaseWaitMsg )
|
|
break;
|
|
Tag = Lex( InputString );
|
|
|
|
DPRINT( OSC, ("[WaitMsg: '%s'\n", PleaseWaitMsg ) );
|
|
}
|
|
break;
|
|
#endif
|
|
|
|
case TOKEN_ACTION:
|
|
{
|
|
PCHAR pAction = GetString( InputString );
|
|
if ( !pAction )
|
|
break;
|
|
if ( Lexstrcmpni( pAction, "LOGIN", 5 ) == 0 ) {
|
|
DPRINT( OSC, ("[Screen Action: LOGIN]\n") );
|
|
LoginScreen = TRUE;
|
|
} else if ( Lexstrcmpni( pAction, "AUTOENTER", 9 ) == 0 ) {
|
|
DPRINT( OSC, ("[Screen Action: AUTOENTER]\n") );
|
|
AutoEnter = TRUE;
|
|
} else {
|
|
DPRINT( OSC, ("[Screen Action?] %s\n", pAction) );
|
|
}
|
|
OscHeapFree( pAction );
|
|
}
|
|
// fall thru
|
|
|
|
default:
|
|
Tag = Lex( InputString );
|
|
break;
|
|
}
|
|
|
|
}
|
|
return Tag;
|
|
}
|
|
|
|
//
|
|
// OSCMLTagState( )
|
|
//
|
|
enum TOKENS
|
|
OSCMLTagState(
|
|
IN PCHAR * InputString
|
|
)
|
|
{
|
|
#ifdef HEADLESS_SRV
|
|
ULONG y;
|
|
#endif
|
|
enum TOKENS Tag = TOKEN_START;
|
|
|
|
TraceFunc( "OSCMLTagState( )\n" );
|
|
|
|
BlpSendEscape(ScreenAttributes);
|
|
BlpClearScreen();
|
|
|
|
ScreenX = LeftMargin;
|
|
ScreenY = SCREEN_TOP;
|
|
|
|
while ( Tag != TOKEN_EOF )
|
|
{
|
|
switch (Tag)
|
|
{
|
|
case TOKEN_TITLE:
|
|
Tag = TitleTagState( InputString );
|
|
break;
|
|
|
|
case TOKEN_FOOTER:
|
|
Tag = FooterTagState( InputString );
|
|
break;
|
|
|
|
case TOKEN_META:
|
|
Tag = MetaTagState( InputString );
|
|
break;
|
|
|
|
case TOKEN_BODY:
|
|
Tag = BodyTagState( InputString );
|
|
break;
|
|
|
|
case TOKEN_ENDHTML:
|
|
return Tag; // exit state
|
|
|
|
default:
|
|
Tag = Lex( InputString );
|
|
break;
|
|
}
|
|
}
|
|
return Tag;
|
|
}
|
|
|
|
// **************************************************************************
|
|
//
|
|
// "User" Section
|
|
//
|
|
// **************************************************************************
|
|
|
|
|
|
//
|
|
// ProcessEmptyScreen( )
|
|
//
|
|
// Process a screen that has no input controls
|
|
//
|
|
CHAR
|
|
ProcessEmptyScreen(
|
|
OUT PCHAR OutputString
|
|
)
|
|
{
|
|
ULONG Key;
|
|
UCHAR KeyAscii;
|
|
|
|
TraceFunc("ProcessEmptyScreen()\n");
|
|
|
|
while (TRUE) {
|
|
|
|
#ifdef EFI
|
|
//
|
|
// disable EFI watchdog when waiting for user response
|
|
//
|
|
DisableEFIWatchDog();
|
|
#endif
|
|
do {
|
|
|
|
Key = BlpGetKey();
|
|
|
|
} while (Key == 0);
|
|
#ifdef EFI
|
|
//
|
|
// reset efi watchdog
|
|
//
|
|
SetEFIWatchDog(EFI_WATCHDOG_TIMEOUT);
|
|
#endif
|
|
|
|
KeyAscii = (UCHAR)(Key & (ULONG)0xff);
|
|
|
|
// If it is enter/esc/F1/F3, check if the screen expects that.
|
|
|
|
if ( Key == F1_KEY ) {
|
|
if ( F1Key ) {
|
|
SpecialAction = F1Key->Action;
|
|
if ( F1Key->ScreenName ) {
|
|
strcpy( OutputString, F1Key->ScreenName );
|
|
strcat( OutputString, "\n" );
|
|
}
|
|
return KeyAscii;
|
|
}
|
|
|
|
} else if ( Key == F3_KEY ) {
|
|
if ( F3Key ) {
|
|
SpecialAction = F3Key->Action;
|
|
if ( F3Key->ScreenName ) {
|
|
strcpy( OutputString, F3Key->ScreenName );
|
|
strcat( OutputString, "\n" );
|
|
}
|
|
return KeyAscii;
|
|
}
|
|
|
|
#if defined(_BUILDING_OSDISP_)
|
|
} else if ( Key == F5_KEY ) {
|
|
SpecialAction = ACTION_REFRESH;
|
|
return KeyAscii;
|
|
#endif
|
|
|
|
} else if ( KeyAscii == (UCHAR)(ESCAPE_KEY & 0xFF) ) {
|
|
if ( EscKey ) {
|
|
SpecialAction = EscKey->Action;
|
|
if ( EscKey->ScreenName ) {
|
|
strcpy( OutputString, EscKey->ScreenName );
|
|
strcat( OutputString, "\n" );
|
|
}
|
|
return KeyAscii;
|
|
}
|
|
} else {
|
|
// assume any other key is the Enter key
|
|
if ( EnterKey ) {
|
|
SpecialAction = EnterKey->Action;
|
|
if ( EnterKey->ScreenName ) {
|
|
strcpy( OutputString, EnterKey->ScreenName );
|
|
strcat( OutputString, "\n" );
|
|
}
|
|
return KeyAscii;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// ProcessInputControl( )
|
|
//
|
|
ULONG
|
|
ProcessInputControl(
|
|
LPINPUTSTRUCT Input
|
|
)
|
|
{
|
|
CHAR InputBuffer[ MAX_INPUT_BUFFER_LENGTH ];
|
|
int MaxLength;
|
|
int CurrentLength;
|
|
ULONG Key;
|
|
UCHAR KeyAscii;
|
|
|
|
TraceFunc("ProcessInputControl()\n");
|
|
|
|
//
|
|
// variable types are not actually printed or processed.
|
|
// return TAB_KEY to move to the next available input control
|
|
//
|
|
if ((Input->Type & CT_VARIABLE) == CT_VARIABLE) {
|
|
return TAB_KEY;
|
|
}
|
|
|
|
if ( Input->Value ) {
|
|
CurrentLength = strlen( Input->Value );
|
|
strcpy( InputBuffer, Input->Value );
|
|
OscHeapFree( Input->Value );
|
|
Input->Value = NULL;
|
|
} else {
|
|
CurrentLength = 0;
|
|
InputBuffer[0] = '\0';
|
|
}
|
|
|
|
MaxLength = Input->Size;
|
|
if ( Input->MaxLength ) {
|
|
MaxLength = Input->MaxLength;
|
|
}
|
|
|
|
// paranoid
|
|
if ( CurrentLength > MaxLength ) {
|
|
CurrentLength = MaxLength;
|
|
InputBuffer[CurrentLength] = '\0';
|
|
}
|
|
|
|
if (Input->CurrentPosition > CurrentLength ) {
|
|
Input->CurrentPosition = CurrentLength;
|
|
}
|
|
|
|
// paint the "[ .... ]"
|
|
BlpSendEscapeBold( ScreenAttributes );
|
|
BlpPositionCursor( Input->X, Input->Y );
|
|
PRINT(TEXT("["), 1*sizeof(TCHAR));
|
|
BlpPositionCursor( Input->X + Input->Size + BRACKETS, Input->Y );
|
|
PRINT(TEXT("]") ,1*sizeof(TCHAR));
|
|
BlpSendEscape( ScreenAttributes );
|
|
|
|
//
|
|
// Let the user type in a string, showing the text at the current
|
|
// location. Returns the key used to exit (so we can distinguish
|
|
// enter and tab).
|
|
//
|
|
#ifdef EFI
|
|
//
|
|
// disable efi watchdog
|
|
//
|
|
DisableEFIWatchDog();
|
|
#endif
|
|
while (TRUE) {
|
|
int DrawSize;
|
|
|
|
// Get a keystroke -- this returns (from exp.asm):
|
|
//
|
|
// If no key is available, returns 0 (which BlpGetKeyWithBlink hides)
|
|
//
|
|
// If ASCII character is available, LSB 0 is ASCII code
|
|
// LSB 1 is keyboard scan code
|
|
// If extended character is available, LSB 0 is extended ASCII code
|
|
// LSB 1 is keyboard scan code
|
|
//
|
|
// NOTE: For extended keys LSB 0 seems to be 0, not the ASCII code
|
|
// (which makes sense since they have no ASCII codes).
|
|
|
|
if ( (Input->Type & CT_PASSWORD) && InputBuffer[Input->CurrentPosition] )
|
|
{
|
|
Key = BlpGetKeyWithBlink( Input->X + Input->CurrentPosition + 2 - Input->FirstVisibleChar,
|
|
Input->Y,
|
|
'*' );
|
|
} else {
|
|
Key = BlpGetKeyWithBlink( Input->X + Input->CurrentPosition + 2 - Input->FirstVisibleChar,
|
|
Input->Y,
|
|
InputBuffer[Input->CurrentPosition] );
|
|
}
|
|
|
|
#if 0
|
|
// TEMP: Show value of any key pressed near the bottom of the screen
|
|
|
|
ARC_DISPLAY_INVERSE_VIDEO();
|
|
ARC_DISPLAY_POSITION_CURSOR(0, 20);
|
|
BlPrint(TEXT("%x\n"), Key);
|
|
ARC_DISPLAY_ATTRIBUTES_OFF();
|
|
#endif
|
|
|
|
KeyAscii = (UCHAR)(Key & (ULONG)0xff);
|
|
|
|
// If it is enter/esc/tab/backtab/F1/F3, then we are done.
|
|
|
|
if ((Key == BACKTAB_KEY) || (Key == F1_KEY) || (Key == F3_KEY) ||
|
|
(KeyAscii == ENTER_KEY) || (KeyAscii == TAB_KEY) ||
|
|
(KeyAscii == (UCHAR)(ESCAPE_KEY & 0xFF)) ||
|
|
(Key == DOWN_ARROW) || (Key == UP_ARROW) || (Key == F5_KEY)) {
|
|
break;
|
|
}
|
|
|
|
// If it is backspace, then go back one character.
|
|
|
|
if ( KeyAscii == (UCHAR)(BKSP_KEY & 0xFF)
|
|
&& Input->CurrentPosition != 0
|
|
&& CurrentLength != 0 ) {
|
|
Input->CurrentPosition--;
|
|
memcpy( &InputBuffer[Input->CurrentPosition],
|
|
&InputBuffer[Input->CurrentPosition+1],
|
|
CurrentLength - Input->CurrentPosition + 1 );
|
|
CurrentLength--;
|
|
|
|
if ( Input->CurrentPosition <= Input->FirstVisibleChar ) {
|
|
Input->FirstVisibleChar -= Input->Size / 2;
|
|
if ( Input->FirstVisibleChar < 0 ) {
|
|
Input->FirstVisibleChar = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( Key == LEFT_KEY ) {
|
|
Input->CurrentPosition--;
|
|
if ( Input->CurrentPosition < 0 ) {
|
|
Input->CurrentPosition = 0;
|
|
}
|
|
}
|
|
|
|
if ( Key == RIGHT_KEY && Input->CurrentPosition < CurrentLength ) {
|
|
Input->CurrentPosition++;
|
|
}
|
|
|
|
if ( Key == END_KEY ) {
|
|
Input->CurrentPosition = CurrentLength;
|
|
}
|
|
|
|
if ( Key == HOME_KEY ) {
|
|
Input->CurrentPosition = 0;
|
|
}
|
|
|
|
if ( Key == DEL_KEY
|
|
&& CurrentLength != 0
|
|
&& Input->CurrentPosition != CurrentLength ) {
|
|
memcpy( &InputBuffer[Input->CurrentPosition],
|
|
&InputBuffer[Input->CurrentPosition+1],
|
|
CurrentLength - Input->CurrentPosition + 1 );
|
|
|
|
CurrentLength--;
|
|
}
|
|
|
|
if ( Key == INS_KEY ) {
|
|
InsertMode = 1 - InsertMode;
|
|
}
|
|
|
|
// For now allow any printable character
|
|
|
|
if ((KeyAscii >= ' ') && (KeyAscii <= '~')) {
|
|
|
|
//
|
|
// If we are at the maximum, then don't allow it.
|
|
//
|
|
if (Input->CurrentPosition > MaxLength || CurrentLength >= MaxLength ) {
|
|
continue;
|
|
}
|
|
|
|
if ( !InsertMode ) {
|
|
// add or replace a character
|
|
InputBuffer[Input->CurrentPosition] = KeyAscii;
|
|
Input->CurrentPosition++;
|
|
if ( Input->CurrentPosition > CurrentLength ) {
|
|
CurrentLength++;
|
|
InputBuffer[CurrentLength] = '\0';
|
|
}
|
|
} else {
|
|
// insert character
|
|
memmove( &InputBuffer[Input->CurrentPosition+1],
|
|
&InputBuffer[Input->CurrentPosition],
|
|
CurrentLength - Input->CurrentPosition );
|
|
CurrentLength++;
|
|
InputBuffer[CurrentLength] = '\0';
|
|
InputBuffer[Input->CurrentPosition] = KeyAscii;
|
|
Input->CurrentPosition++;
|
|
}
|
|
}
|
|
|
|
if ( Input->CurrentPosition > Input->FirstVisibleChar + Input->Size ) {
|
|
Input->FirstVisibleChar = Input->CurrentPosition - Input->Size;
|
|
}
|
|
|
|
//
|
|
// Scroll Adjuster Section
|
|
//
|
|
|
|
DrawSize = Input->Size + 1;
|
|
|
|
// Paranoid
|
|
if ( Input->CurrentPosition < Input->FirstVisibleChar ) {
|
|
Input->FirstVisibleChar = Input->CurrentPosition;
|
|
}
|
|
|
|
BlpPositionCursor( Input->X + 1, Input->Y );
|
|
if ( Input->FirstVisibleChar <= 0 ) {
|
|
Input->FirstVisibleChar = 0;
|
|
PRINT( SpaceString, 1*sizeof(TCHAR) );
|
|
} else {
|
|
PRINT( TEXT("<"), 1*sizeof(TCHAR) );
|
|
}
|
|
|
|
if ( DrawSize > CurrentLength - Input->FirstVisibleChar ) {
|
|
DrawSize = CurrentLength - Input->FirstVisibleChar;
|
|
}
|
|
|
|
DPRINT( OSC, ("CurrentPosition: %u\tFirstVisibleChar:%u\tCurrentLength:%u\tDrawSize:%u\n",
|
|
Input->CurrentPosition, Input->FirstVisibleChar, CurrentLength, DrawSize ) );
|
|
|
|
if ( Input->Type & CT_PASSWORD ) {
|
|
int i;
|
|
|
|
for( i = Input->FirstVisibleChar; i < Input->FirstVisibleChar + DrawSize; i++ )
|
|
{
|
|
PRINT( TEXT("*"), 1*sizeof(TCHAR) );
|
|
}
|
|
|
|
PRINT( SpaceString, 1*sizeof(TCHAR) );
|
|
} else {
|
|
#ifdef UNICODE
|
|
int i;
|
|
for (i = 0; i < DrawSize; i++) {
|
|
WCHAR wc = (WCHAR)InputBuffer[Input->FirstVisibleChar+i];
|
|
PRINT( &wc, 1*sizeof(WCHAR));
|
|
}
|
|
#else
|
|
PRINT( &InputBuffer[Input->FirstVisibleChar], DrawSize );
|
|
#endif
|
|
PRINT( SpaceString, 1*sizeof(TCHAR) );
|
|
break;
|
|
}
|
|
|
|
BlpPositionCursor( Input->X + Input->Size + BRACKETS - 1, Input->Y );
|
|
if ( Input->FirstVisibleChar + DrawSize < CurrentLength
|
|
&& CurrentLength > Input->Size ) {
|
|
PRINT( TEXT(">"), 1*sizeof(TCHAR) );
|
|
} else {
|
|
PRINT( SpaceString, 1*sizeof(TCHAR) );
|
|
}
|
|
}
|
|
#ifdef EFI
|
|
//
|
|
// reset EFI watchdog
|
|
//
|
|
SetEFIWatchDog(EFI_WATCHDOG_TIMEOUT);
|
|
#endif
|
|
|
|
// copy the buffer
|
|
Input->Value = OscHeapAlloc( CurrentLength + 1 );
|
|
if ( Input->Value ) {
|
|
memcpy( Input->Value, InputBuffer, CurrentLength + 1 );
|
|
}
|
|
|
|
// UN-paint the "[ .... ]"
|
|
BlpPositionCursor( Input->X, Input->Y );
|
|
PRINT(SpaceString, 1*sizeof(TCHAR));
|
|
BlpPositionCursor( Input->X + Input->Size + BRACKETS, Input->Y );
|
|
PRINT(TEXT(" ") ,1*sizeof(TCHAR));
|
|
|
|
// If we exited on a standard key return the ASCII value, otherwise
|
|
// the full key value.
|
|
|
|
if (KeyAscii != 0) {
|
|
return (ULONG)KeyAscii;
|
|
} else {
|
|
return Key;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// ShowSelectedOptions( )
|
|
//
|
|
void
|
|
ShowSelectedOptions(
|
|
LPSELECTSTRUCT Select,
|
|
LPOPTIONSTRUCT Option,
|
|
int YPosition,
|
|
BOOLEAN Hovering
|
|
)
|
|
{
|
|
TraceFunc( "ShowSelectedOptions( )\n" );
|
|
if ( Option->Flags == OF_SELECTED ) {
|
|
BlpSendEscapeBold( ScreenAttributes );
|
|
}
|
|
|
|
if ( Hovering == TRUE ) {
|
|
BlpSendEscapeReverse( ScreenAttributes );
|
|
}
|
|
|
|
// Erase
|
|
BlpPositionCursor( Select->X, YPosition );
|
|
PRINT( SpaceString, Select->Width*sizeof(TCHAR) );
|
|
|
|
// Draw
|
|
BlpPositionCursor( Select->X, YPosition );
|
|
if ( Option->Displayed )
|
|
#ifdef UNICODE
|
|
{
|
|
ULONG i;
|
|
WCHAR wc;
|
|
for (i = 0; i< strlen(Option->Displayed); i++) {
|
|
wc = (WCHAR)(Option->Displayed)[i];
|
|
PRINT( &wc, sizeof(WCHAR));
|
|
}
|
|
}
|
|
#else
|
|
PRINTL( Option->Displayed );
|
|
#endif
|
|
|
|
if ( Option->Value )
|
|
DPRINT( OSC, ("[Option Y=%u] %s %s\n", YPosition, Option->Value, (Hovering ? "HIGHLITED" : "")) );
|
|
|
|
BlpSendEscape( ScreenAttributes );
|
|
|
|
if ( TipArea && Hovering == TRUE ) {
|
|
// Draw help area
|
|
int SaveLeftMargin = LeftMargin;
|
|
int SaveRightMargin = RightMargin;
|
|
int SaveScreenY = ScreenY;
|
|
int SaveScreenX = ScreenX;
|
|
int SaveScreenBottom = ScreenBottom;
|
|
|
|
// Set the drawing area
|
|
ScreenX = TipArea->X;
|
|
ScreenY = TipArea->Y;
|
|
LeftMargin = TipArea->LeftMargin;
|
|
RightMargin = TipArea->RightMargin;
|
|
ScreenBottom = TipArea->Y + TipArea->Size;
|
|
|
|
// Clear the old help text out
|
|
BlpPositionCursor( TipArea->X, TipArea->Y );
|
|
PRINT( SpaceString, (TipArea->RightMargin - TipArea->X)*sizeof(TCHAR) );
|
|
|
|
for ( YPosition = TipArea->Y + 1; YPosition < ScreenBottom ; YPosition++ )
|
|
{
|
|
BlpPositionCursor( TipArea->LeftMargin, YPosition );
|
|
PRINT( SpaceString, (TipArea->RightMargin - TipArea->LeftMargin)*sizeof(TCHAR) );
|
|
}
|
|
|
|
// Print it!
|
|
DPRINT( OSC, ("[Options Tip X=%u Y=%u Left=%u Right=%u Bottom=%u] %s\n",
|
|
ScreenX, ScreenY, LeftMargin, RightMargin, ScreenBottom, Option->Tip) );
|
|
BlpPrintString( Option->Tip, Option->EndTip );
|
|
|
|
// Restore
|
|
ScreenX = SaveScreenX;
|
|
ScreenY = SaveScreenY;
|
|
RightMargin = SaveRightMargin;
|
|
LeftMargin = SaveLeftMargin;
|
|
ScreenBottom = SaveScreenBottom;;
|
|
}
|
|
}
|
|
|
|
//
|
|
// DrawSelectControl( )
|
|
//
|
|
// Select controls get drawn from the bottom up.
|
|
//
|
|
void
|
|
DrawSelectControl(
|
|
LPSELECTSTRUCT Select,
|
|
int OptionCount
|
|
)
|
|
{
|
|
LPOPTIONSTRUCT Option = Select->FirstVisibleSelection;
|
|
|
|
TraceFunc( "DrawSelectControl( )\n" );
|
|
|
|
ScreenY = Select->Y + ( OptionCount < Select->Size ? OptionCount : Select->Size ) - 1;
|
|
|
|
while ( Option )
|
|
{
|
|
if ( Option->Type & CT_OPTION ) {
|
|
BOOLEAN b = (Select->CurrentSelection == Option);
|
|
ShowSelectedOptions( Select, Option, ScreenY, b );
|
|
ScreenY--;
|
|
}
|
|
|
|
if ( ScreenY < Select->Y || Option->Next == Select )
|
|
break;
|
|
|
|
Option = Option->Next;
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// ProcessSelectControl( )
|
|
//
|
|
ULONG
|
|
ProcessSelectControl(
|
|
LPSELECTSTRUCT Select
|
|
)
|
|
{
|
|
ULONG Key;
|
|
int OptionCount = 0;
|
|
LPOPTIONSTRUCT Option;
|
|
int fMultipleControls = FALSE;
|
|
|
|
TraceFunc("ProcessSelectControl()\n");
|
|
|
|
#ifdef EFI
|
|
//
|
|
// disable EFI watchdog
|
|
//
|
|
DisableEFIWatchDog();
|
|
#endif
|
|
|
|
// find out about the control
|
|
Option = ScreenControls;
|
|
while( Option )
|
|
{
|
|
if ( Option->Type & CT_OPTION ) {
|
|
|
|
OptionCount++;
|
|
|
|
} else if ( (Option->Type & CT_SELECT) == 0 ) {
|
|
// not the only control on the screen
|
|
DPRINT( OSC, ("[Select] Not the only control on the screen.\n") );
|
|
fMultipleControls = TRUE;
|
|
}
|
|
|
|
if ( Option->Next == Select )
|
|
break;
|
|
|
|
Option = Option->Next;
|
|
}
|
|
// if this is the first thru and nothing else
|
|
if ( !Select->CurrentSelection && Option ) {
|
|
DPRINT( OSC, ("[Select] Setting CurrentSelection to the first item '%s'\n", Option->Value) );
|
|
Select->CurrentSelection = Option;
|
|
}
|
|
// ensure the current selection is visible
|
|
EnsureSelectionVisible:
|
|
if ( Select->Size < 2 ) {
|
|
// single line - show the current selection
|
|
Select->FirstVisibleSelection = Select->CurrentSelection;
|
|
} else if ( OptionCount <= Select->Size ) {
|
|
// the number of options is less than or equal to the size
|
|
// of the dialog so simply set the first visible equal to
|
|
// the last OPTION in the list.
|
|
|
|
Select->FirstVisibleSelection = ScreenControls;
|
|
while ( Select->FirstVisibleSelection )
|
|
{
|
|
if ( Select->FirstVisibleSelection->Type & CT_OPTION )
|
|
break;
|
|
|
|
Select->FirstVisibleSelection = Select->FirstVisibleSelection->Next;
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// The number of options is greater than the display size so we
|
|
// need to figure out the "best" bottom item.
|
|
//
|
|
ULONG Lines;
|
|
ULONG Count;
|
|
LPOPTIONSTRUCT TmpOption;
|
|
|
|
//
|
|
// Find the best FirstVisibleSelection if we already have previously chosen one.
|
|
//
|
|
Count = 0;
|
|
if (Select->FirstVisibleSelection != NULL) {
|
|
|
|
//
|
|
// This code checks to see if the current selection is visible with the
|
|
// current first visible selection.
|
|
//
|
|
TmpOption = ScreenControls;
|
|
|
|
while (TmpOption->Next != Select) {
|
|
|
|
if (TmpOption == Select->FirstVisibleSelection) {
|
|
Count++;
|
|
} else if (Count != 0) {
|
|
Count++;
|
|
}
|
|
|
|
if (TmpOption == Select->CurrentSelection) {
|
|
break;
|
|
}
|
|
|
|
TmpOption = TmpOption->Next;
|
|
|
|
|
|
}
|
|
|
|
if (TmpOption->Next == Select) {
|
|
Count++;
|
|
}
|
|
|
|
//
|
|
// It is, so just display the list.
|
|
//
|
|
if ((Count != 0) && (Count <= (ULONG)(Select->Size))) {
|
|
goto EndFindVisibleSelection;
|
|
}
|
|
|
|
//
|
|
// It is not visible, but since we have a FirstVisibleSelection, we can
|
|
// move that around to make it visible.
|
|
//
|
|
|
|
|
|
//
|
|
// The current selection comes before the first visible one, so move
|
|
// first visible to the current selection.
|
|
//
|
|
if (Count == 0) {
|
|
Select->FirstVisibleSelection = Select->CurrentSelection;
|
|
goto EndFindVisibleSelection;
|
|
}
|
|
|
|
//
|
|
// Count is greater than the screen size, so we move up First visible
|
|
// until count is the screen size.
|
|
//
|
|
TmpOption = ScreenControls;
|
|
|
|
while (TmpOption->Next != Select) {
|
|
|
|
if (TmpOption == Select->FirstVisibleSelection) {
|
|
|
|
Select->FirstVisibleSelection = TmpOption->Next;
|
|
Count--;
|
|
|
|
if (Count == (ULONG)(Select->Size)) {
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
TmpOption = TmpOption->Next;
|
|
|
|
}
|
|
|
|
goto EndFindVisibleSelection;
|
|
}
|
|
|
|
//
|
|
// There is no FirstVisibleSelection, so we choose one that places the current
|
|
// selection near the top of the screen, displaying the first item, if possible.
|
|
//
|
|
|
|
TmpOption = Select->CurrentSelection;
|
|
Lines = 0;
|
|
Count = 0;
|
|
|
|
//
|
|
// Count the number of items before our current selection.
|
|
//
|
|
while (TmpOption->Next != Select) {
|
|
|
|
TmpOption = TmpOption->Next;
|
|
Lines++;
|
|
|
|
}
|
|
|
|
//
|
|
// Subtract off that many items from what is left for below the selection.
|
|
//
|
|
Lines = (ULONG)((Lines < (ULONG)(Select->Size)) ? Lines : Select->Size - 1);
|
|
Lines = Select->Size - Lines - 1;
|
|
|
|
//
|
|
// If more than a screen before, make this the bottom and move on.
|
|
//
|
|
if (Lines == 0) {
|
|
Select->FirstVisibleSelection = Select->CurrentSelection;
|
|
goto EndFindVisibleSelection;
|
|
}
|
|
|
|
|
|
TmpOption = ScreenControls;
|
|
|
|
//
|
|
// Count the number of items below the current selection
|
|
//
|
|
while (TmpOption != Select->CurrentSelection) {
|
|
|
|
TmpOption = TmpOption->Next;
|
|
Count++;
|
|
|
|
}
|
|
|
|
if (Count < Lines) {
|
|
|
|
//
|
|
// Not enough items to fill the screen, use the last item.
|
|
//
|
|
Select->FirstVisibleSelection = ScreenControls;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Count back until we reach what will be our bottom item.
|
|
//
|
|
TmpOption = ScreenControls;
|
|
|
|
while (Count != Lines) {
|
|
|
|
TmpOption = TmpOption->Next;
|
|
Count--;
|
|
|
|
}
|
|
|
|
Select->FirstVisibleSelection = TmpOption;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
EndFindVisibleSelection:
|
|
|
|
// paranoid
|
|
if ( !Select->FirstVisibleSelection ) {
|
|
Select->FirstVisibleSelection = ScreenControls;
|
|
}
|
|
|
|
while ( TRUE )
|
|
{
|
|
UCHAR KeyAscii = 0;
|
|
|
|
DrawSelectControl( Select, OptionCount );
|
|
Option = Select->CurrentSelection; // remember this
|
|
|
|
if ( OptionCount == 0
|
|
|| ( Select->AutoSelect == FALSE && OptionCount == 1 ))
|
|
{ // empty selection control or no AUTO select
|
|
do {
|
|
Key = BlpGetKey();
|
|
} while ( Key == 0 );
|
|
|
|
KeyAscii = (UCHAR)(Key & (ULONG)0xff);
|
|
}
|
|
else if ( OptionCount != 1 )
|
|
{ // more than one choice... do the usual
|
|
ULONG CurrentTick, NewTick;
|
|
int TimeoutCounter = 0;
|
|
|
|
// Show any help for this choice
|
|
// BlpShowMenuHelp(psInfo, psInfo->Data[CurChoice].VariableName);
|
|
|
|
CurrentTick = GET_COUNTER();
|
|
do {
|
|
Key = BlpGetKey();
|
|
|
|
if ( Select->Timeout )
|
|
{
|
|
NewTick = GET_COUNTER();
|
|
if ((NewTick < CurrentTick) || ((NewTick - CurrentTick) >= BLINK_RATE))
|
|
{
|
|
CHAR Buffer[4];
|
|
CurrentTick = NewTick;
|
|
|
|
TimeoutCounter++;
|
|
|
|
//
|
|
// TODO: Update the timer value displayed
|
|
//
|
|
|
|
if ( TimeoutCounter >= Select->Timeout )
|
|
{
|
|
Key = ENTER_KEY; // fake return
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
} while (Key == 0);
|
|
|
|
KeyAscii = (UCHAR)(Key & (ULONG)0xff);
|
|
|
|
//
|
|
// User pressed a key, so stop doing the timer
|
|
//
|
|
if ( Select->Timeout ) {
|
|
|
|
Select->Timeout = 0;
|
|
|
|
//
|
|
// TODO: Erase the timer
|
|
//
|
|
}
|
|
}
|
|
else if ( !fMultipleControls ) // && OptionCount == 1
|
|
{ // only once choice... auto-accept it
|
|
//
|
|
// Fake return press....
|
|
//
|
|
DPRINT( OSC, ( "[Select] Auto accepting the only option available\n") );
|
|
Key = KeyAscii = ENTER_KEY;
|
|
}
|
|
|
|
if ( Select->Flags & OF_MULTIPLE ) {
|
|
if ( KeyAscii == 32 && Select->CurrentSelection) {
|
|
if ( Select->CurrentSelection->Flags & OF_SELECTED ) {
|
|
Select->CurrentSelection->Flags &= ~OF_SELECTED; // turn off
|
|
} else {
|
|
Select->CurrentSelection->Flags |= OF_SELECTED; // turn on
|
|
}
|
|
}
|
|
} else {
|
|
if ( KeyAscii == ENTER_KEY && Select->CurrentSelection ) {
|
|
Select->CurrentSelection->Flags |= OF_SELECTED; // turn on
|
|
}
|
|
}
|
|
|
|
if ((Key == BACKTAB_KEY) || (Key == F1_KEY) || (Key == F3_KEY) ||
|
|
(KeyAscii == ENTER_KEY) || (KeyAscii == TAB_KEY) ||
|
|
(KeyAscii == (UCHAR)(ESCAPE_KEY & 0xFF)) ||
|
|
(Key == F5_KEY)) {
|
|
// Undraw the selection bar to give user feedback that something has
|
|
// happened
|
|
Select->CurrentSelection = NULL;
|
|
DrawSelectControl( Select, OptionCount );
|
|
break;
|
|
}
|
|
|
|
|
|
if ( OptionCount ) {
|
|
|
|
if (Key == DOWN_ARROW) {
|
|
DPRINT( OSC, ("[KeyPress] DOWN_ARROW\n") );
|
|
|
|
Select->CurrentSelection = ScreenControls;
|
|
|
|
while ( Select->CurrentSelection && Select->CurrentSelection->Next != Option )
|
|
{
|
|
Select->CurrentSelection = Select->CurrentSelection ->Next;
|
|
}
|
|
|
|
if ( Select->CurrentSelection )
|
|
DPRINT( OSC, ("[Select] CurrentSelection = '%s'\n", Select->CurrentSelection->Value) );
|
|
|
|
// paranoid
|
|
if ( !Select->CurrentSelection )
|
|
Select->CurrentSelection = Option;
|
|
|
|
goto EnsureSelectionVisible;
|
|
|
|
} else if ( Key == UP_ARROW ) {
|
|
DPRINT( OSC, ("[KeyPress] UP_ARROW\n") );
|
|
|
|
if ( Select->CurrentSelection->Next != Select ) {
|
|
Select->CurrentSelection = Select->CurrentSelection->Next;
|
|
DPRINT( OSC, ("[Select] CurrentSelection = '%s'\n", Select->CurrentSelection->Value) );
|
|
}
|
|
|
|
// paranoid
|
|
if ( !Select->CurrentSelection )
|
|
Select->CurrentSelection = Option;
|
|
|
|
goto EnsureSelectionVisible;
|
|
|
|
} else if ( Key == END_KEY ) {
|
|
DPRINT( OSC, ("[KeyPress] END_KEY\n") );
|
|
|
|
Select->CurrentSelection = ScreenControls;
|
|
|
|
while( Select->CurrentSelection && (Select->CurrentSelection->Type & CT_OPTION) == 0 )
|
|
{
|
|
Select->CurrentSelection = Select->CurrentSelection->Next;
|
|
}
|
|
|
|
if ( Select->CurrentSelection )
|
|
DPRINT( OSC, ("[Select] CurrentSelection = '%s'\n", Select->CurrentSelection->Value) );
|
|
|
|
// paranoid
|
|
if ( !Select->CurrentSelection )
|
|
Select->CurrentSelection = Option;
|
|
|
|
goto EnsureSelectionVisible;
|
|
|
|
} else if ( Key == HOME_KEY ) {
|
|
DPRINT( OSC, ("[KeyPress] HOME_KEY\n") );
|
|
|
|
Select->CurrentSelection = ScreenControls;
|
|
|
|
while ( Select->CurrentSelection && Select->CurrentSelection->Next != Select )
|
|
{
|
|
Select->CurrentSelection = Select->CurrentSelection ->Next;
|
|
}
|
|
|
|
if ( Select->CurrentSelection )
|
|
DPRINT( OSC, ("[Select] CurrentSelection = '%s'\n", Select->CurrentSelection->Value) );
|
|
|
|
// paranoid
|
|
if ( !Select->CurrentSelection )
|
|
Select->CurrentSelection = Option;
|
|
|
|
goto EnsureSelectionVisible;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef EFI
|
|
//
|
|
// reset watchdog
|
|
//
|
|
SetEFIWatchDog(EFI_WATCHDOG_TIMEOUT);
|
|
#endif
|
|
return Key;
|
|
}
|
|
|
|
|
|
//
|
|
// BlFixupLoginScreenInputs( )
|
|
//
|
|
// On an input screen, split a USERNAME that has an @ in it, keeping
|
|
// the part before the @ in USERNAME and moving the part after to
|
|
// USERDOMAIN.
|
|
//
|
|
void
|
|
BlFixupLoginScreenInputs(
|
|
)
|
|
{
|
|
LPCONTROLSTRUCT CurrentControl;
|
|
LPINPUTSTRUCT UserNameControl = NULL;
|
|
LPINPUTSTRUCT UserDomainControl = NULL;
|
|
PCHAR AtSign;
|
|
|
|
//
|
|
// First loop through and find the USERNAME and USERDOMAIN input
|
|
// controls.
|
|
//
|
|
|
|
CurrentControl = ScreenControls;
|
|
while( CurrentControl ) {
|
|
|
|
LPINPUTSTRUCT Input = (LPINPUTSTRUCT) CurrentControl;
|
|
|
|
if ( ( Input->Type & CT_TEXT ) && ( Input->Name != NULL ) ) {
|
|
if ( Lexstrcmpni( Input->Name, "USERNAME", 8 ) == 0 ) {
|
|
UserNameControl = Input;
|
|
} else if ( Lexstrcmpni( Input->Name, "USERDOMAIN", 10 ) == 0 ) {
|
|
UserDomainControl = Input;
|
|
}
|
|
}
|
|
CurrentControl = CurrentControl->Next;
|
|
}
|
|
|
|
//
|
|
// If we found them, fix them up if necessary.
|
|
//
|
|
|
|
if ( ( UserNameControl != NULL ) &&
|
|
( UserNameControl->Value != NULL ) &&
|
|
( UserDomainControl != NULL) ) {
|
|
|
|
AtSign = strchr(UserNameControl->Value, '@');
|
|
if (AtSign != NULL) {
|
|
*AtSign = '\0'; // terminate UserNameControl->Value before the @
|
|
if ( UserDomainControl->Value != NULL ) {
|
|
OscHeapFree( UserDomainControl->Value ); // throw away old domain
|
|
}
|
|
UserDomainControl->Value = OscHeapAlloc( strlen(AtSign+1) + 1 );
|
|
if ( UserDomainControl->Value != NULL ) {
|
|
strcpy(UserDomainControl->Value, AtSign+1); // copy part after the @
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//
|
|
// ProcessControlResults( )
|
|
//
|
|
// Process a screen that has input controls
|
|
//
|
|
void
|
|
ProcessControlResults(
|
|
IN PCHAR OutputString
|
|
)
|
|
{
|
|
LPCONTROLSTRUCT CurrentControl;
|
|
LPCONTROLSTRUCT LastControl;
|
|
|
|
BOOLEAN CheckAdminPassword_AlreadyChecked = FALSE;
|
|
BOOLEAN CheckAdminPasswordConfirm_AlreadyChecked = FALSE;
|
|
|
|
// start clean
|
|
OutputString[0] = '\0';
|
|
|
|
if ( EnterKey ) {
|
|
SpecialAction = EnterKey->Action;
|
|
if ( EnterKey->ScreenName ) {
|
|
strcpy( OutputString, EnterKey->ScreenName );
|
|
strcat( OutputString, "\n" );
|
|
}
|
|
}
|
|
|
|
if ( LoginScreen == TRUE ) {
|
|
SpecialAction = ACTION_LOGIN;
|
|
UserName[0] = '\0';
|
|
Password[0] = '\0';
|
|
DomainName[0] = '\0';
|
|
BlFixupLoginScreenInputs(); // split username with @ in it
|
|
AuthenticationType = OSCHOICE_AUTHENETICATE_TYPE_NTLM_V1;
|
|
}
|
|
|
|
CurrentControl = ScreenControls;
|
|
while( CurrentControl ) {
|
|
|
|
BOOLEAN CheckAdminPasswordConfirm = FALSE;
|
|
BOOLEAN CheckAdminPassword = FALSE;
|
|
|
|
switch( CurrentControl->Type & (CT_TEXT | CT_PASSWORD | CT_RESET | CT_SELECT | CT_OPTION | CT_VARIABLE))
|
|
{
|
|
case CT_TEXT:
|
|
case CT_PASSWORD:
|
|
{
|
|
LPINPUTSTRUCT Input = (LPINPUTSTRUCT) CurrentControl;
|
|
BOOLEAN LocalOnly;
|
|
|
|
DPRINT( OSC, ("About to check a password.\n") );
|
|
|
|
if ( (Input->Type & (CT_PASSWORD)) &&
|
|
(Input->Type & (CT_LOCAL)) &&
|
|
Input->Name ) {
|
|
|
|
LocalOnly = TRUE;
|
|
|
|
if( _strnicmp(Input->Name, "*ADMINISTRATORPASSWORDCONFIRM", 29) == 0 ) {
|
|
CheckAdminPasswordConfirm = TRUE;
|
|
CheckAdminPasswordConfirm_AlreadyChecked = TRUE;
|
|
DPRINT( OSC, ("About to check the ADMINISTRATORPASSWORDCONFIRM\n") );
|
|
} else if( _strnicmp( Input->Name, "*ADMINISTRATORPASSWORD", 22) == 0 ) {
|
|
CheckAdminPassword = TRUE;
|
|
CheckAdminPassword_AlreadyChecked = TRUE;
|
|
DPRINT( OSC, ("About to check the ADMINISTRATORPASSWORD\n") );
|
|
} else {
|
|
DPRINT( OSC, ("It's a local password, but not Admin or AdminConfirm.\n") );
|
|
}
|
|
|
|
} else {
|
|
LocalOnly = FALSE;
|
|
DPRINT( OSC, ("It's NOT a local password.\n") );
|
|
}
|
|
|
|
DPRINT(
|
|
OSC,
|
|
("variable %s will%sbe transmitted to the server.\n",
|
|
Input->Name,
|
|
LocalOnly ? " not " : " " ) );
|
|
|
|
|
|
if (Input->Name && !LocalOnly ) {
|
|
strcat( OutputString, Input->Name );
|
|
strcat( OutputString, "=" );
|
|
}
|
|
|
|
if ( (Input->Value) && (Input->Encoding == ET_OWF)) {
|
|
|
|
PCHAR TmpLmOwfPassword = NULL;
|
|
PCHAR TmpNtOwfPassword = NULL;
|
|
CHAR TmpHashedPW[(LM_OWF_PASSWORD_SIZE+NT_OWF_PASSWORD_SIZE+2)*2];
|
|
|
|
UNICODE_STRING TmpNtPassword;
|
|
PWCHAR UnicodePassword;
|
|
ULONG PasswordLen, i;
|
|
PCHAR OutputLoc;
|
|
CHAR c;
|
|
|
|
DPRINT( OSC, ("This entry has ET_OWF tagged.\n") );
|
|
|
|
PasswordLen = strlen(Input->Value);
|
|
|
|
UnicodePassword = (PWCHAR)OscHeapAlloc(PasswordLen * sizeof(WCHAR));
|
|
TmpLmOwfPassword = (PCHAR)OscHeapAlloc(LM_OWF_PASSWORD_SIZE);
|
|
TmpNtOwfPassword = (PCHAR)OscHeapAlloc(NT_OWF_PASSWORD_SIZE);
|
|
|
|
if( (UnicodePassword != NULL) &&
|
|
(TmpLmOwfPassword != NULL) &&
|
|
(TmpNtOwfPassword != NULL) ) {
|
|
|
|
//
|
|
// Do a quick conversion of the password to Unicode.
|
|
//
|
|
|
|
TmpNtPassword.Length = (USHORT)(PasswordLen * sizeof(WCHAR));
|
|
TmpNtPassword.MaximumLength = TmpNtPassword.Length;
|
|
TmpNtPassword.Buffer = UnicodePassword;
|
|
|
|
for (i = 0; i < PasswordLen; i++) {
|
|
UnicodePassword[i] = (WCHAR)(Input->Value[i]);
|
|
}
|
|
|
|
|
|
|
|
BlOwfPassword(Input->Value, &TmpNtPassword, TmpLmOwfPassword, TmpNtOwfPassword);
|
|
|
|
|
|
|
|
//
|
|
// Output the two OWF passwords as hex chars. If
|
|
// the value is the administrator password and
|
|
// should only be stored locally, then
|
|
// save it in our global variable. Otherwise put
|
|
// it in the output buffer.
|
|
//
|
|
OutputLoc = TmpHashedPW;
|
|
|
|
|
|
for (i = 0; i < LM_OWF_PASSWORD_SIZE; i++) {
|
|
c = TmpLmOwfPassword[i];
|
|
*(OutputLoc++) = rghex [(c >> 4) & 0x0F] ;
|
|
*(OutputLoc++) = rghex [c & 0x0F] ;
|
|
}
|
|
for (i = 0; i < NT_OWF_PASSWORD_SIZE; i++) {
|
|
c = TmpNtOwfPassword[i];
|
|
*(OutputLoc++) = rghex [(c >> 4) & 0x0F] ;
|
|
*(OutputLoc++) = rghex [c & 0x0F] ;
|
|
}
|
|
*OutputLoc = '\0';
|
|
|
|
DPRINT( OSC, ("Hashed Password: %s\n", TmpHashedPW) );
|
|
|
|
if (!LocalOnly) {
|
|
strcat(OutputString,TmpHashedPW);
|
|
} else {
|
|
|
|
|
|
if( CheckAdminPassword ) {
|
|
strcpy( AdministratorPassword, TmpHashedPW );
|
|
DPRINT( OSC, ("AdministratorPassword 1: %s\n", AdministratorPassword) );
|
|
}
|
|
|
|
if( CheckAdminPasswordConfirm ) {
|
|
strcpy( AdministratorPasswordConfirm, TmpHashedPW );
|
|
DPRINT( OSC, ("AdministratorPasswordConfirm 1: %s\n", AdministratorPasswordConfirm) );
|
|
|
|
}
|
|
|
|
|
|
#if 0
|
|
if (AdministratorPassword[0] != '\0') {
|
|
if (strcmp(
|
|
AdministratorPassword,
|
|
TmpHashedPW)) {
|
|
//
|
|
// the passwords didn't match. make the server
|
|
// display MATCHPW.OSC and reset the admin password
|
|
// for the next time around
|
|
//
|
|
DPRINT(
|
|
OSC,
|
|
("Administrator passwords didn't match, force MATCHPW.OSC.\n" ) );
|
|
|
|
strcpy( OutputString, "MATCHPW\n" );
|
|
AdministratorPassword[0] = '\0';
|
|
} else {
|
|
strncpy(
|
|
AdministratorPassword,
|
|
TmpHashedPW,
|
|
sizeof(AdministratorPassword)-1 );
|
|
}
|
|
}
|
|
#endif
|
|
OutputLoc = OutputString + strlen(OutputString);
|
|
}
|
|
|
|
OscHeapFree((PCHAR)UnicodePassword);
|
|
OscHeapFree(TmpLmOwfPassword);
|
|
OscHeapFree(TmpNtOwfPassword);
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
DPRINT( OSC, ("This entry does NOT have ET_OWF tagged.\n") );
|
|
|
|
if( LocalOnly ) {
|
|
//
|
|
// Load the appropriate password.
|
|
//
|
|
if( CheckAdminPassword ) {
|
|
strcpy( AdministratorPassword, (Input->Value ? Input->Value : "") );
|
|
DPRINT( OSC, ("I'm setting the Administrator password to %s\n", AdministratorPassword) );
|
|
}
|
|
|
|
if( CheckAdminPasswordConfirm ) {
|
|
strcpy( AdministratorPasswordConfirm, (Input->Value ? Input->Value : "") );
|
|
DPRINT( OSC, ("I'm setting the AdministratorConfirm password to %s\n", AdministratorPasswordConfirm) );
|
|
}
|
|
} else {
|
|
strcat( OutputString, (Input->Value ? Input->Value : "") );
|
|
}
|
|
}
|
|
|
|
//
|
|
// If both passwords have been processed, check them to see if they match.
|
|
//
|
|
if( CheckAdminPassword_AlreadyChecked &&
|
|
CheckAdminPasswordConfirm_AlreadyChecked ) {
|
|
|
|
DPRINT( OSC, ("Both Admin and AdminConfirm passwords are set. About to check if they match.\n") );
|
|
|
|
if( strcmp( AdministratorPassword, AdministratorPasswordConfirm ) ) {
|
|
|
|
//
|
|
// the passwords didn't match. make the server
|
|
// display MATCHPW.OSC and reset the admin password
|
|
// for the next time around
|
|
//
|
|
DPRINT( OSC, ("Administrator passwords didn't match, force MATCHPW.OSC.\n" ) );
|
|
|
|
strcpy( OutputString, "MATCHPW\n" );
|
|
AdministratorPassword[0] = '\0';
|
|
AdministratorPasswordConfirm[0] = '\0';
|
|
|
|
} else {
|
|
DPRINT( OSC, ("Administrator passwords match.\n" ) );
|
|
|
|
//
|
|
// See if the Admin password is empty. If so, then put our
|
|
// super-secret tag on the end to show everyone that it's really
|
|
// empty, not just uninitialized.
|
|
//
|
|
if( AdministratorPassword[0] == '\0' ) {
|
|
|
|
DPRINT( OSC, ("Administrator password is empty, so set our 'it is null' flag.\n" ) );
|
|
AdministratorPassword[OSC_ADMIN_PASSWORD_LEN-1] = 0xFF;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( SpecialAction == ACTION_LOGIN
|
|
&& (Input->Name != NULL)
|
|
&& (Input->Value != NULL) ) {
|
|
if ( Lexstrcmpni( Input->Name, "USERNAME", 8 ) == 0 ) {
|
|
strncpy( UserName, Input->Value, sizeof(UserName)-1 );
|
|
UserName[sizeof(UserName)-1] = '\0';
|
|
} else if ( Lexstrcmpni( Input->Name, "*PASSWORD", 9 ) == 0 ) {
|
|
strncpy( Password, Input->Value, sizeof(Password)-1 );
|
|
Password[sizeof(Password)-1] = '\0';
|
|
} else if ( Lexstrcmpni( Input->Name, "USERDOMAIN", 10 ) == 0 ) {
|
|
strncpy( DomainName, Input->Value, sizeof(DomainName)-1 );
|
|
DomainName[sizeof(DomainName)-1] = '\0';
|
|
}
|
|
}
|
|
|
|
if (!LocalOnly) {
|
|
strcat( OutputString, "\n" );
|
|
}
|
|
}
|
|
break;
|
|
|
|
case CT_SELECT:
|
|
{
|
|
CHAR NotFirst = FALSE;
|
|
LPOPTIONSTRUCT Option = ScreenControls;
|
|
LPSELECTSTRUCT Select = (LPSELECTSTRUCT) CurrentControl;
|
|
if ( Select->Name ) {
|
|
strcat( OutputString, Select->Name );
|
|
strcat( OutputString, "=" );
|
|
}
|
|
|
|
while( Option && Option->Type == CT_OPTION )
|
|
{
|
|
if ( Option->Flags == OF_SELECTED ) {
|
|
if ( NotFirst ) {
|
|
strcat( OutputString, "+" );
|
|
}
|
|
|
|
if ( Option->Value ) {
|
|
strcat( OutputString, Option->Value );
|
|
NotFirst = TRUE;
|
|
}
|
|
}
|
|
|
|
Option = Option->Next;
|
|
}
|
|
strcat( OutputString, "\n" );
|
|
}
|
|
break;
|
|
case CT_VARIABLE:
|
|
{
|
|
LPINPUTSTRUCT Input = (LPINPUTSTRUCT) CurrentControl;
|
|
strcat( OutputString, Input->Name );
|
|
strcat( OutputString, "=" );
|
|
strcat( OutputString, Input->Value );
|
|
strcat( OutputString, "\n" );
|
|
|
|
if (SpecialAction == ACTION_LOGIN) {
|
|
//
|
|
// check if ntlm v2 is enabled on the server.
|
|
//
|
|
if ((strcmp(Input->Name,"NTLMV2Enabled") == 0) &&
|
|
(strcmp(Input->Value,"1") == 0)) {
|
|
AuthenticationType = OSCHOICE_AUTHENETICATE_TYPE_NTLM_V2;
|
|
}
|
|
|
|
//
|
|
// check if the server gave us the current file time
|
|
// we need this so that we can do ntlm v2 style
|
|
// authentication.
|
|
//
|
|
if (strcmp(Input->Name,"ServerUTCFileTime") == 0) {
|
|
SetFileTimeFromTimeString(
|
|
Input->Value,
|
|
&GlobalFileTime,
|
|
&ArcTimeForUTCTime);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
CurrentControl = CurrentControl->Next;
|
|
}
|
|
}
|
|
|
|
//
|
|
// ProcessScreenControls( )
|
|
//
|
|
// Process a screen that has input controls
|
|
//
|
|
CHAR
|
|
ProcessScreenControls(
|
|
OUT PCHAR OutputString
|
|
)
|
|
{
|
|
ULONG Key;
|
|
UCHAR KeyAscii;
|
|
LPCONTROLSTRUCT CurrentControl;
|
|
LPCONTROLSTRUCT LastControl;
|
|
|
|
TraceFunc("ProcessScreenControls()\n");
|
|
|
|
// find the first control
|
|
LastControl = ScreenControls;
|
|
CurrentControl = ScreenControls;
|
|
while( LastControl ) {
|
|
CurrentControl = LastControl;
|
|
LastControl = CurrentControl->Next;
|
|
}
|
|
|
|
while (TRUE) {
|
|
|
|
TopOfLoop:
|
|
// show activation on the control
|
|
switch( CurrentControl->Type & (CT_PASSWORD | CT_TEXT | CT_SELECT) )
|
|
{
|
|
case CT_PASSWORD:
|
|
case CT_TEXT:
|
|
Key = ProcessInputControl( (LPINPUTSTRUCT) CurrentControl );
|
|
break;
|
|
|
|
case CT_SELECT:
|
|
Key = ProcessSelectControl( (LPSELECTSTRUCT) CurrentControl );
|
|
break;
|
|
|
|
default:
|
|
// non-processing control - skip it
|
|
CurrentControl = CurrentControl->Next;
|
|
if ( !CurrentControl ) {
|
|
CurrentControl = ScreenControls;
|
|
}
|
|
goto TopOfLoop;
|
|
}
|
|
|
|
LastControl = CurrentControl;
|
|
|
|
KeyAscii = (UCHAR)(Key & (ULONG)0xff);
|
|
|
|
// If it is enter/esc/F1/F3, check if the screen expects that.
|
|
|
|
if ( Key == F1_KEY ) {
|
|
|
|
DPRINT( OSC, ("[KeyPress] F1_KEY\n") );
|
|
|
|
if ( F1Key ) {
|
|
SpecialAction = F1Key->Action;
|
|
if ( F1Key->ScreenName ) {
|
|
strcpy( OutputString, F1Key->ScreenName );
|
|
strcat( OutputString, "\n" );
|
|
}
|
|
return KeyAscii;
|
|
}
|
|
|
|
} else if ( Key == F3_KEY ) {
|
|
|
|
DPRINT( OSC, ("[KeyPress] F3_KEY\n") );
|
|
|
|
if ( F3Key ) {
|
|
SpecialAction = F3Key->Action;
|
|
if ( F3Key->ScreenName ) {
|
|
strcpy( OutputString, F3Key->ScreenName );
|
|
strcat( OutputString, "\n" );
|
|
}
|
|
return KeyAscii;
|
|
}
|
|
|
|
#if defined(_BUILDING_OSDISP_)
|
|
} else if ( Key == F5_KEY ) {
|
|
SpecialAction = ACTION_REFRESH;
|
|
return KeyAscii;
|
|
#endif
|
|
|
|
} else if ( KeyAscii == (UCHAR)(ESCAPE_KEY & 0xFF) ) {
|
|
|
|
DPRINT( OSC, ("[KeyPress] ESCAPE_KEY\n") );
|
|
|
|
if ( EscKey ) {
|
|
SpecialAction = EscKey->Action;
|
|
if ( EscKey->ScreenName ) {
|
|
strcpy( OutputString, EscKey->ScreenName );
|
|
strcat( OutputString, "\n" );
|
|
}
|
|
return KeyAscii;
|
|
}
|
|
|
|
} else if ( KeyAscii == TAB_KEY || Key == DOWN_ARROW ) {
|
|
|
|
DPRINT( OSC, ("[KeyPress] TAB_KEY or DOWN_ARROW\n") );
|
|
|
|
CurrentControl = ScreenControls;
|
|
|
|
while ( CurrentControl->Next != LastControl && // next is current one, so stop
|
|
CurrentControl->Next != NULL ) // at end of list, so we must have been at
|
|
// the start, so stop here to loop around
|
|
{
|
|
CurrentControl = CurrentControl->Next;
|
|
}
|
|
|
|
} else if ( Key == BACKTAB_KEY || Key == UP_ARROW ) {
|
|
|
|
DPRINT( OSC, ("[KeyPress] BACKTAB_KEY or UP_ARROW\n") );
|
|
|
|
CurrentControl = CurrentControl->Next;
|
|
if (!CurrentControl) {
|
|
CurrentControl = ScreenControls; // loop around if needed
|
|
}
|
|
|
|
} else if ( KeyAscii == ENTER_KEY ) {
|
|
|
|
DPRINT( OSC, ("[KeyPress] ENTER_KEY\n") );
|
|
|
|
ProcessControlResults( OutputString );
|
|
|
|
return KeyAscii;
|
|
}
|
|
|
|
if ( !CurrentControl ) {
|
|
CurrentControl = LastControl;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
// BlProcessScreen( )
|
|
//
|
|
CHAR
|
|
BlProcessScreen(
|
|
IN PCHAR InputString,
|
|
OUT PCHAR OutputString
|
|
)
|
|
{
|
|
#ifdef HEADLESS_SRV
|
|
ULONG y;
|
|
#endif
|
|
CHAR chReturn;
|
|
enum TOKENS Tag;
|
|
|
|
#ifdef _TRACE_FUNC_
|
|
TraceFunc( "BlProcessScreen( " );
|
|
DPRINT( OSC, ("InputString = 0x%08x, OutputString = 0x%08x )\n", InputString, OutputString) );
|
|
#endif
|
|
|
|
// reset our "heap"
|
|
OscHeapInitialize( );
|
|
|
|
// reset the screen variables
|
|
ScreenAttributes = WhiteOnBlueAttributes;
|
|
SpecialAction = ACTION_NOP;
|
|
LeftMargin = 1;
|
|
RightMargin = 80;
|
|
ScreenX = LeftMargin;
|
|
ScreenY = SCREEN_TOP;
|
|
F1Key = NULL;
|
|
F3Key = NULL;
|
|
EnterKey = NULL;
|
|
EscKey = NULL;
|
|
ScreenControls = NULL;
|
|
PreformattedMode = FALSE;
|
|
LoginScreen = FALSE;
|
|
AutoEnter = FALSE;
|
|
InsertMode = FALSE;
|
|
TipArea = NULL;
|
|
|
|
if (BlIsTerminalConnected()) {
|
|
ScreenBottom = HEADLESS_SCREEN_HEIGHT;
|
|
} else {
|
|
ScreenBottom = SCREEN_BOTTOM;
|
|
}
|
|
#if defined(PLEASE_WAIT)
|
|
PleaseWaitMsg = NULL;
|
|
#endif
|
|
|
|
BlpSendEscape(ScreenAttributes);
|
|
BlpClearScreen();
|
|
|
|
|
|
Tag = Lex( &InputString );
|
|
while (Tag != TOKEN_EOF )
|
|
{
|
|
switch (Tag)
|
|
{
|
|
case TOKEN_HTML:
|
|
Tag = OSCMLTagState( &InputString );
|
|
break;
|
|
|
|
case TOKEN_ENDHTML:
|
|
Tag = TOKEN_EOF; // exit state
|
|
break;
|
|
|
|
default:
|
|
Tag = ImpliedBodyTagState( &InputString );
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Remove any buffered keys to prevent blipping thru the screens.
|
|
// NOTE we call BlGetKey() directly, not BlpGetKey(), so we only
|
|
// remove real keystrokes, not the "auto-enter" keystroke.
|
|
while ( BlGetKey( ) != 0 )
|
|
; // NOP on purpose
|
|
|
|
if ( ScreenControls ) {
|
|
chReturn = ProcessScreenControls( OutputString );
|
|
} else {
|
|
chReturn = ProcessEmptyScreen( OutputString );
|
|
}
|
|
|
|
// Erase footer to give user feedback that the screen is being
|
|
// processed.
|
|
BlpSendEscapeReverse(ScreenAttributes);
|
|
BlpPositionCursor( 1, ScreenBottom );
|
|
|
|
#ifdef _IN_OSDISP_
|
|
PRINT( SpaceString, 79*sizeof(TCHAR) );
|
|
#else
|
|
PRINT( SpaceString, BlTerminalConnected
|
|
? 79*sizeof(TCHAR)
|
|
: 80*sizeof(TCHAR) );
|
|
#endif
|
|
|
|
#if defined(PLEASE_WAIT)
|
|
if ( PleaseWaitMsg ) {
|
|
BlpPositionCursor( 1, ScreenBottom );
|
|
#ifdef UNICODE
|
|
{
|
|
ULONG i;
|
|
WCHAR wc;
|
|
for (i = 0; i< strlen(PleaseWaitMsg);i++) {
|
|
wc = (WCHAR)PleaseWaitMsg[i];
|
|
PRINT( &wc, 1*sizeof(WCHAR));
|
|
}
|
|
}
|
|
#else
|
|
PRINTL( PleaseWaitMsg );
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
BlpSendEscape(ScreenAttributes);
|
|
return chReturn;
|
|
}
|