|
|
/*++
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; }
|