XTLDR Rewrite #7
704
xtldr2/textui.c
Normal file
704
xtldr2/textui.c
Normal file
@ -0,0 +1,704 @@
|
||||
/**
|
||||
* PROJECT: ExectOS
|
||||
* COPYRIGHT: See COPYING.md in the top level directory
|
||||
* FILE: xtldr/textui.c
|
||||
* DESCRIPTION: Text console User Interface (TUI) support for XT Boot Loader
|
||||
* DEVELOPERS: Rafal Kupiec <belliash@codingworkshop.eu.org>
|
||||
*/
|
||||
|
||||
#include <xtldr.h>
|
||||
|
||||
|
||||
/* TUI dialog box attributes */
|
||||
#define TUI_DIALOG_GENERIC_BOX 1
|
||||
#define TUI_DIALOG_ERROR_BOX 2
|
||||
#define TUI_DIALOG_ACTIVE_BUTTON 4
|
||||
#define TUI_DIALOG_INACTIVE_BUTTON 8
|
||||
#define TUI_DIALOG_ACTIVE_INPUT_FIELD 16
|
||||
#define TUI_DIALOG_INACTIVE_INPUT_FIELD 32
|
||||
#define TUI_DIALOG_PROGRESS_BAR 64
|
||||
|
||||
#define TUI_MAX_DIALOG_WIDTH 100
|
||||
|
||||
typedef struct _XTBL_DIALOG_HANDLE
|
||||
{
|
||||
UCHAR Attributes;
|
||||
UINT_PTR ResX;
|
||||
UINT_PTR ResY;
|
||||
UINT_PTR PosX;
|
||||
UINT_PTR PosY;
|
||||
UINT_PTR Width;
|
||||
UINT_PTR Height;
|
||||
} XTBL_DIALOG_HANDLE, *PXTBL_DIALOG_HANDLE;
|
||||
|
||||
XTCDECL
|
||||
VOID
|
||||
BlpDetermineDialogBoxSize(IN PXTBL_DIALOG_HANDLE Handle,
|
||||
IN PWCHAR Message)
|
||||
{
|
||||
UINT_PTR Width, Height, LineLength;
|
||||
SIZE_T Index, MessageLength;
|
||||
UCHAR Attributes;
|
||||
ULONG Mask;
|
||||
|
||||
/* Set minimum dialog window size */
|
||||
Height = 4;
|
||||
Width = 36;
|
||||
|
||||
/* Zero line length */
|
||||
LineLength = 0;
|
||||
|
||||
/* Adjust window height according to enabled components */
|
||||
Mask = 1;
|
||||
Attributes = Handle->Attributes;
|
||||
while(Mask)
|
||||
{
|
||||
/* Check enabled components that affect dialog window size */
|
||||
switch(Attributes & Mask)
|
||||
{
|
||||
case TUI_DIALOG_ACTIVE_BUTTON:
|
||||
case TUI_DIALOG_INACTIVE_BUTTON:
|
||||
Height += 1;
|
||||
break;
|
||||
case TUI_DIALOG_ACTIVE_INPUT_FIELD:
|
||||
case TUI_DIALOG_INACTIVE_INPUT_FIELD:
|
||||
case TUI_DIALOG_PROGRESS_BAR:
|
||||
Height += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Update component attributes mask */
|
||||
Attributes &= ~Mask;
|
||||
Mask <<= 1;
|
||||
}
|
||||
|
||||
/* Check if input field is active */
|
||||
if(Handle->Attributes & (TUI_DIALOG_ACTIVE_INPUT_FIELD | TUI_DIALOG_INACTIVE_INPUT_FIELD))
|
||||
{
|
||||
/* Set maximum dialog window width to fit input field */
|
||||
Width = TUI_MAX_DIALOG_WIDTH;
|
||||
}
|
||||
|
||||
/* Get message length and count dialog window dimensions */
|
||||
MessageLength = RtlWideStringLength(Message, 0);
|
||||
for(Index = 0; Index < MessageLength; Index++)
|
||||
{
|
||||
/* Check if this is multiline message */
|
||||
if(Message[Index] == L'\n' || Index == MessageLength - 1)
|
||||
{
|
||||
/* Check if this line exceeds current dialog window width */
|
||||
if(LineLength > Width)
|
||||
{
|
||||
/* Update dialog window width */
|
||||
Width = LineLength;
|
||||
}
|
||||
/* Increase dialog window height to fit next line */
|
||||
Height++;
|
||||
LineLength = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Increase dialog window width to fit next character */
|
||||
LineLength++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Add more space to dialog window to fit side borders */
|
||||
Width += 4;
|
||||
|
||||
/* Get console resolution */
|
||||
BlConsoleQueryMode(&Handle->ResX, &Handle->ResY);
|
||||
|
||||
/* Make sure dialog window fits in the buffer */
|
||||
if(Width > TUI_MAX_DIALOG_WIDTH)
|
||||
{
|
||||
/* Set maximum dialog window width */
|
||||
Width = TUI_MAX_DIALOG_WIDTH;
|
||||
}
|
||||
|
||||
/* Make sure dialog window fits on the screen (X axis) and it is not too small for input field */
|
||||
if(Width > (Handle->ResX - 2))
|
||||
{
|
||||
/* Set maximum dialog window width */
|
||||
Width = Handle->ResX - 2;
|
||||
}
|
||||
|
||||
/* Make sure dialog window fits on the screen (Y axis)*/
|
||||
if(Height > (Handle->ResY - 2))
|
||||
{
|
||||
/* Set maximum dialog window height */
|
||||
Height = Handle->ResY - 2;
|
||||
}
|
||||
|
||||
/* Set dialog window final dimensions */
|
||||
Handle->PosX = (Handle->ResX - Width) / 2;
|
||||
Handle->PosY = (Handle->ResY - Height) / 2;
|
||||
Handle->Width = Width;
|
||||
Handle->Height = Height;
|
||||
}
|
||||
|
||||
XTCDECL
|
||||
VOID
|
||||
BlpDrawDialogBox(IN PXTBL_DIALOG_HANDLE Handle,
|
||||
IN PWCHAR Caption,
|
||||
IN PWCHAR Message)
|
||||
{
|
||||
WCHAR BoxLine[TUI_MAX_DIALOG_WIDTH];
|
||||
PWCHAR MsgLine, LastMsgLine;
|
||||
UINT_PTR Line, PosX, PosY;
|
||||
SIZE_T CaptionLength;
|
||||
UCHAR DialogColor;
|
||||
|
||||
/* Set dialog colors */
|
||||
if(Handle->Attributes & TUI_DIALOG_ERROR_BOX)
|
||||
{
|
||||
/* Error dialog with red background and brown button */
|
||||
DialogColor = EFI_TEXT_BGCOLOR_RED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Generic dialog with blue background and cyan button */
|
||||
DialogColor = EFI_TEXT_BGCOLOR_BLUE;
|
||||
}
|
||||
|
||||
/* Get caption length */
|
||||
CaptionLength = RtlWideStringLength(Caption, 0);
|
||||
|
||||
/* Set dialog box colors */
|
||||
BlSetConsoleAttributes(DialogColor | 0x0F);
|
||||
|
||||
/* Iterate through dialog box lines */
|
||||
for(PosY = Handle->PosY; PosY < Handle->PosY + Handle->Height; PosY++)
|
||||
{
|
||||
/* Set cursor position in the appropriate place */
|
||||
BlSetCursorPosition(Handle->PosX, PosY);
|
||||
|
||||
/* Draw dialog box */
|
||||
if(PosY == Handle->PosY)
|
||||
{
|
||||
/* Draw top line of the dialog box, starting from the left corner */
|
||||
BoxLine[0] = EFI_TEXT_BOX_DOWN_RIGHT;
|
||||
BoxLine[1] = EFI_TEXT_BOX_VERTICAL_LEFT;
|
||||
|
||||
/* Fill caption area with spaces */
|
||||
for(PosX = 2; PosX < CaptionLength + 4; PosX++)
|
||||
{
|
||||
BoxLine[PosX] = ' ';
|
||||
}
|
||||
|
||||
/* End caption area with vertical line */
|
||||
BoxLine[CaptionLength + 4] = EFI_TEXT_BOX_VERTICAL_RIGHT;
|
||||
|
||||
/* Draw bottom line */
|
||||
for(PosX = CaptionLength + 5; PosX < Handle->Width - 1; PosX++)
|
||||
{
|
||||
BoxLine[PosX] = EFI_TEXT_BOX_HORIZONTAL;
|
||||
}
|
||||
|
||||
/* End with top right corner */
|
||||
BoxLine[Handle->Width - 1] = EFI_TEXT_BOX_DOWN_LEFT;
|
||||
}
|
||||
else if(PosY == Handle->PosY + Handle->Height - 1)
|
||||
{
|
||||
/* Draw bottom line of the dialog box, starting from the left corner */
|
||||
BoxLine[0] = EFI_TEXT_BOX_UP_LEFT;
|
||||
|
||||
/* Fill bottom with horizontal line */
|
||||
for(PosX = 1; PosX < Handle->Width - 1; PosX++)
|
||||
{
|
||||
BoxLine[PosX] = EFI_TEXT_BOX_HORIZONTAL;
|
||||
}
|
||||
|
||||
/* End with bottom right corner */
|
||||
BoxLine[Handle->Width - 1] = EFI_TEXT_BOX_UP_RIGHT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Draw the middle of the dialog box */
|
||||
BoxLine[0] = EFI_TEXT_BOX_VERTICAL;
|
||||
|
||||
/* Fill dialog box with spaces */
|
||||
for(PosX = 1; PosX < Handle->Width - 1; PosX++)
|
||||
{
|
||||
BoxLine[PosX] = ' ';
|
||||
}
|
||||
|
||||
/* End with vertical line */
|
||||
BoxLine[Handle->Width - 1] = EFI_TEXT_BOX_VERTICAL;
|
||||
}
|
||||
|
||||
/* Add null terminator to the end of the line */
|
||||
BoxLine[Handle->Width] = 0;
|
||||
|
||||
/* Write the line to the console */
|
||||
BlConsoleWrite(BoxLine);
|
||||
}
|
||||
|
||||
/* Write dialog box caption */
|
||||
BlSetCursorPosition(Handle->PosX + 3, Handle->PosY);
|
||||
BlConsolePrint(L"%S", Caption);
|
||||
|
||||
/* Tokenize dialog box message */
|
||||
MsgLine = RtlTokenizeWideString(Message, L"\n", &LastMsgLine);
|
||||
|
||||
/* Iterate through message lines */
|
||||
Line = 0;
|
||||
while(MsgLine)
|
||||
{
|
||||
/* Write line in the dialog box */
|
||||
BlSetCursorPosition(Handle->PosX + 2, Handle->PosY + 2 + Line);
|
||||
BlConsolePrint(L"%S", MsgLine);
|
||||
|
||||
/* Get next line */
|
||||
MsgLine = RtlTokenizeWideString(NULL, L"\n", &LastMsgLine);
|
||||
Line++;
|
||||
}
|
||||
}
|
||||
|
||||
XTCDECL
|
||||
VOID
|
||||
BlpDrawDialogButton(IN PXTBL_DIALOG_HANDLE Handle)
|
||||
{
|
||||
ULONG ButtonColor, TextColor;
|
||||
|
||||
/* Set dialog button colors */
|
||||
if(Handle->Attributes & TUI_DIALOG_ACTIVE_BUTTON)
|
||||
{
|
||||
/* This is an active button */
|
||||
if(Handle->Attributes & TUI_DIALOG_ERROR_BOX)
|
||||
{
|
||||
/* This is an error dialog box */
|
||||
ButtonColor = EFI_TEXT_BGCOLOR_BROWN;
|
||||
TextColor = EFI_TEXT_FGCOLOR_WHITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a generic dialog box */
|
||||
ButtonColor = EFI_TEXT_BGCOLOR_CYAN;
|
||||
TextColor = EFI_TEXT_FGCOLOR_WHITE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is an inactive button */
|
||||
ButtonColor = EFI_TEXT_BGCOLOR_LIGHTGRAY;
|
||||
TextColor = EFI_TEXT_FGCOLOR_BLACK;
|
||||
}
|
||||
|
||||
/* Disable cursor and draw dialog button */
|
||||
BlConsoleDisableCursor();
|
||||
BlSetConsoleAttributes(ButtonColor | TextColor);
|
||||
BlSetCursorPosition(Handle->ResX / 2 - 4, Handle->PosY + Handle->Height - 2);
|
||||
BlConsolePrint(L"[ OK ]");
|
||||
}
|
||||
|
||||
XTCDECL
|
||||
VOID
|
||||
BlpDrawDialogInputField(IN PXTBL_DIALOG_HANDLE Handle,
|
||||
IN PWCHAR InputFieldText)
|
||||
{
|
||||
WCHAR InputField[TUI_MAX_DIALOG_WIDTH];
|
||||
ULONG InputColor, TextColor;
|
||||
UINT_PTR Index, Position;
|
||||
|
||||
/* Set dialog button colors */
|
||||
if(Handle->Attributes & TUI_DIALOG_ACTIVE_INPUT_FIELD)
|
||||
{
|
||||
/* This is an active input field */
|
||||
if(Handle->Attributes & TUI_DIALOG_ERROR_BOX)
|
||||
{
|
||||
/* This is an error dialog box */
|
||||
InputColor = EFI_TEXT_BGCOLOR_BROWN;
|
||||
TextColor = EFI_TEXT_FGCOLOR_WHITE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a generic dialog box */
|
||||
InputColor = EFI_TEXT_BGCOLOR_CYAN;
|
||||
TextColor = EFI_TEXT_FGCOLOR_WHITE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is an inactive input field */
|
||||
InputColor = EFI_TEXT_BGCOLOR_LIGHTGRAY;
|
||||
TextColor = EFI_TEXT_FGCOLOR_BLACK;
|
||||
}
|
||||
|
||||
/* Set progress bar color and position */
|
||||
BlSetConsoleAttributes(InputColor | TextColor);
|
||||
Position = (Handle->Attributes & (TUI_DIALOG_ACTIVE_BUTTON | TUI_DIALOG_INACTIVE_BUTTON)) ? 4 : 3;
|
||||
BlSetCursorPosition(Handle->PosX + 4, Handle->PosY + Handle->Height - Position);
|
||||
|
||||
/* Draw input field */
|
||||
for(Index = 0; Index < Handle->Width - 8; Index++)
|
||||
{
|
||||
/* Fill input field with spaces */
|
||||
InputField[Index] = L' ';
|
||||
}
|
||||
|
||||
/* Disable cursor and write input field to console */
|
||||
BlConsoleDisableCursor();
|
||||
BlConsoleWrite(InputField);
|
||||
|
||||
/* Write input field text */
|
||||
BlSetCursorPosition(Handle->PosX + 4, Handle->PosY + Handle->Height - Position);
|
||||
BlConsoleWrite(InputFieldText);
|
||||
|
||||
/* Check if this is an active input field */
|
||||
if(Handle->Attributes & TUI_DIALOG_ACTIVE_INPUT_FIELD)
|
||||
{
|
||||
/* Enable cursor for active input field */
|
||||
BlConsoleEnableCursor();
|
||||
}
|
||||
}
|
||||
|
||||
XTCDECL
|
||||
VOID
|
||||
BlpDrawDialogProgressBar(IN PXTBL_DIALOG_HANDLE Handle,
|
||||
IN UCHAR Percentage)
|
||||
{
|
||||
UINT_PTR Index, ProgressLength, ProgressBarLength;
|
||||
WCHAR ProgressBar[TUI_MAX_DIALOG_WIDTH];
|
||||
UINT_PTR Position;
|
||||
|
||||
/* Determine progress bar length and calculate progress */
|
||||
ProgressBarLength = Handle->Width - 8;
|
||||
ProgressLength = (ProgressBarLength * Percentage) / 100;
|
||||
|
||||
/* Set progress bar color and position */
|
||||
BlSetConsoleAttributes(EFI_TEXT_FGCOLOR_YELLOW);
|
||||
Position = (Handle->Attributes & (TUI_DIALOG_ACTIVE_BUTTON | TUI_DIALOG_INACTIVE_BUTTON)) ? 4 : 3;
|
||||
BlSetCursorPosition(Handle->PosX + 4, Handle->PosY + Handle->Height - Position);
|
||||
|
||||
/* Draw progress bar */
|
||||
for(Index = 0; Index < ProgressBarLength; Index++)
|
||||
{
|
||||
/* Fill progress bar */
|
||||
if(Index < ProgressLength)
|
||||
{
|
||||
/* Fill with full block */
|
||||
ProgressBar[Index] = EFI_TEXT_BOX_FULL_BLOCK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fill with light block */
|
||||
ProgressBar[Index] = EFI_TEXT_BOX_LIGHT_BLOCK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Terminate progress bar string */
|
||||
ProgressBar[Index] = 0;
|
||||
|
||||
/* Disable cursor and write progress bar to console */
|
||||
BlConsoleDisableCursor();
|
||||
BlConsoleWrite(ProgressBar);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
XTCDECL
|
||||
VOID
|
||||
BlDisplayErrorDialog(IN PWCHAR Caption,
|
||||
IN PWCHAR Message)
|
||||
{
|
||||
XTBL_DIALOG_HANDLE Handle;
|
||||
EFI_INPUT_KEY Key;
|
||||
UINT_PTR Index;
|
||||
|
||||
/* Set dialog window attributes */
|
||||
Handle.Attributes = TUI_DIALOG_ERROR_BOX | TUI_DIALOG_ACTIVE_BUTTON;
|
||||
|
||||
/* Determine dialog window size and position */
|
||||
BlpDetermineDialogBoxSize(&Handle, Message);
|
||||
|
||||
/* Disable cursor and draw dialog box */
|
||||
BlConsoleDisableCursor();
|
||||
BlpDrawDialogBox(&Handle, Caption, Message);
|
||||
|
||||
/* Draw active button */
|
||||
BlpDrawDialogButton(&Handle);
|
||||
|
||||
/* Initialize key stroke */
|
||||
Key.ScanCode = 0;
|
||||
Key.UnicodeChar = 0;
|
||||
|
||||
/* Wait until ENTER or ESC key is pressed */
|
||||
while(Key.ScanCode != 0x17 && Key.UnicodeChar != 0x0D)
|
||||
{
|
||||
/* Wait for key press and read key stroke */
|
||||
EfiSystemTable->BootServices->WaitForEvent(1, &EfiSystemTable->ConIn->WaitForKey, &Index);
|
||||
EfiSystemTable->ConIn->ReadKeyStroke(EfiSystemTable->ConIn, &Key);
|
||||
EfiSystemTable->ConIn->Reset(EfiSystemTable->ConIn, FALSE);
|
||||
}
|
||||
|
||||
/* Clear screen to remove dialog box */
|
||||
BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY);
|
||||
BlConsoleClearScreen();
|
||||
}
|
||||
|
||||
XTCDECL
|
||||
VOID
|
||||
BlDisplayInfoDialog(IN PWCHAR Caption,
|
||||
IN PWCHAR Message)
|
||||
{
|
||||
XTBL_DIALOG_HANDLE Handle;
|
||||
EFI_INPUT_KEY Key;
|
||||
UINT_PTR Index;
|
||||
|
||||
/* Set dialog window attributes */
|
||||
Handle.Attributes = TUI_DIALOG_GENERIC_BOX | TUI_DIALOG_ACTIVE_BUTTON;
|
||||
|
||||
/* Determine dialog window size and position */
|
||||
BlpDetermineDialogBoxSize(&Handle, Message);
|
||||
|
||||
/* Disable cursor and draw dialog box */
|
||||
BlConsoleDisableCursor();
|
||||
BlpDrawDialogBox(&Handle, Caption, Message);
|
||||
|
||||
/* Draw active button */
|
||||
BlpDrawDialogButton(&Handle);
|
||||
|
||||
/* Initialize key stroke */
|
||||
Key.ScanCode = 0;
|
||||
Key.UnicodeChar = 0;
|
||||
|
||||
/* Wait until ENTER or ESC key is pressed */
|
||||
while(Key.ScanCode != 0x17 && Key.UnicodeChar != 0x0D)
|
||||
{
|
||||
/* Wait for key press and read key stroke */
|
||||
EfiSystemTable->BootServices->WaitForEvent(1, &EfiSystemTable->ConIn->WaitForKey, &Index);
|
||||
EfiSystemTable->ConIn->ReadKeyStroke(EfiSystemTable->ConIn, &Key);
|
||||
EfiSystemTable->ConIn->Reset(EfiSystemTable->ConIn, FALSE);
|
||||
}
|
||||
|
||||
/* Clear screen to remove dialog box */
|
||||
BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY);
|
||||
BlConsoleClearScreen();
|
||||
}
|
||||
|
||||
XTCDECL
|
||||
VOID
|
||||
BlDisplayInputDialog(IN PWCHAR Caption,
|
||||
IN PWCHAR Message,
|
||||
IN PWCHAR InputFieldBuffer)
|
||||
{
|
||||
XTBL_DIALOG_HANDLE Handle;
|
||||
SIZE_T InputFieldLength, TextCursorPosition, TextIndex, TextPosition;
|
||||
EFI_INPUT_KEY Key;
|
||||
UINT_PTR Index;
|
||||
|
||||
/* Set dialog window attributes */
|
||||
Handle.Attributes = TUI_DIALOG_GENERIC_BOX | TUI_DIALOG_ACTIVE_INPUT_FIELD | TUI_DIALOG_INACTIVE_BUTTON;
|
||||
|
||||
/* Determine dialog window size and position */
|
||||
BlpDetermineDialogBoxSize(&Handle, Message);
|
||||
|
||||
/* Disable cursor and draw dialog box */
|
||||
BlConsoleDisableCursor();
|
||||
BlpDrawDialogBox(&Handle, Caption, Message);
|
||||
|
||||
/* Draw inactive button */
|
||||
BlpDrawDialogButton(&Handle);
|
||||
|
||||
/* Draw active input field */
|
||||
BlpDrawDialogInputField(&Handle, InputFieldBuffer);
|
||||
|
||||
/* Initialize key stroke */
|
||||
Key.ScanCode = 0;
|
||||
Key.UnicodeChar = 0;
|
||||
|
||||
/* Determine input field length */
|
||||
InputFieldLength = RtlWideStringLength(InputFieldBuffer, 0);
|
||||
if(InputFieldLength > Handle.Width - 8)
|
||||
{
|
||||
InputFieldLength = Handle.Width - 8;
|
||||
}
|
||||
|
||||
/* Start at first character */
|
||||
TextPosition = 0;
|
||||
BlSetCursorPosition(Handle.PosX + 4 + TextPosition, Handle.PosY + Handle.Height - 4);
|
||||
|
||||
/* Wait until ENTER or ESC key is pressed */
|
||||
while(TRUE)
|
||||
{
|
||||
/* Wait for key press and read key stroke */
|
||||
EfiSystemTable->BootServices->WaitForEvent(1, &EfiSystemTable->ConIn->WaitForKey, &Index);
|
||||
EfiSystemTable->ConIn->ReadKeyStroke(EfiSystemTable->ConIn, &Key);
|
||||
EfiSystemTable->ConIn->Reset(EfiSystemTable->ConIn, FALSE);
|
||||
|
||||
/* Check key press scan code */
|
||||
if(Key.ScanCode == 0x17)
|
||||
{
|
||||
/* ESC key pressed, return */
|
||||
break;
|
||||
}
|
||||
else if(Key.UnicodeChar == 0x09)
|
||||
{
|
||||
/* TAB key pressed, toggle input field and button */
|
||||
Handle.Attributes ^= (TUI_DIALOG_ACTIVE_INPUT_FIELD | TUI_DIALOG_INACTIVE_INPUT_FIELD);
|
||||
Handle.Attributes ^= (TUI_DIALOG_ACTIVE_BUTTON | TUI_DIALOG_INACTIVE_BUTTON);
|
||||
}
|
||||
else if(Key.ScanCode == 0x03)
|
||||
{
|
||||
/* RIGHT key pressed, move cursor forward */
|
||||
if(Handle.Attributes & TUI_DIALOG_ACTIVE_INPUT_FIELD && TextPosition < InputFieldLength)
|
||||
{
|
||||
TextPosition++;
|
||||
}
|
||||
}
|
||||
else if(Key.ScanCode == 0x04)
|
||||
{
|
||||
/* LEFT key pressed, move cursor back */
|
||||
if(Handle.Attributes & TUI_DIALOG_ACTIVE_INPUT_FIELD && TextPosition > 0)
|
||||
{
|
||||
TextPosition--;
|
||||
}
|
||||
}
|
||||
else if(Key.ScanCode == 0x05)
|
||||
{
|
||||
/* HOME key pressed, move cursor to the beginning */
|
||||
if(Handle.Attributes & TUI_DIALOG_ACTIVE_INPUT_FIELD)
|
||||
{
|
||||
TextPosition = 0;
|
||||
}
|
||||
}
|
||||
else if(Key.ScanCode == 0x06)
|
||||
{
|
||||
/* END key pressed, move cursor to the end */
|
||||
if(Handle.Attributes & TUI_DIALOG_ACTIVE_INPUT_FIELD)
|
||||
{
|
||||
TextPosition = InputFieldLength;
|
||||
}
|
||||
}
|
||||
else if(Key.ScanCode == 0x08)
|
||||
{
|
||||
/* DELETE key pressed, delete character */
|
||||
if(Handle.Attributes & TUI_DIALOG_ACTIVE_INPUT_FIELD)
|
||||
{
|
||||
if(InputFieldLength > 0 && TextPosition < InputFieldLength)
|
||||
{
|
||||
RtlMoveMemory(InputFieldBuffer + TextPosition, InputFieldBuffer + TextPosition + 1, InputFieldLength - TextPosition);
|
||||
InputFieldLength--;
|
||||
InputFieldBuffer[InputFieldLength] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(Key.UnicodeChar == 0x08)
|
||||
{
|
||||
/* BACKSPACE key pressed, delete character */
|
||||
if(Handle.Attributes & TUI_DIALOG_ACTIVE_INPUT_FIELD)
|
||||
{
|
||||
if(InputFieldLength > 0 && TextPosition > 0 && TextPosition <= InputFieldLength)
|
||||
{
|
||||
TextPosition--;
|
||||
RtlMoveMemory(InputFieldBuffer + TextPosition, InputFieldBuffer + TextPosition + 1, InputFieldLength - TextPosition);
|
||||
InputFieldLength--;
|
||||
InputFieldBuffer[InputFieldLength] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(Key.UnicodeChar == 0x0D)
|
||||
{
|
||||
/* ENTER key pressed */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Other key pressed, add character to the buffer */
|
||||
if(Handle.Attributes & TUI_DIALOG_ACTIVE_INPUT_FIELD && Key.UnicodeChar != 0)
|
||||
{
|
||||
if(InputFieldLength < Handle.Width - 8 - 1 && TextPosition < Handle.Width - 8 - 1)
|
||||
{
|
||||
RtlMoveMemory(InputFieldBuffer + TextPosition + 1, InputFieldBuffer + TextPosition, InputFieldLength - TextPosition);
|
||||
InputFieldBuffer[TextPosition] = Key.UnicodeChar;
|
||||
TextPosition++;
|
||||
InputFieldLength++;
|
||||
InputFieldBuffer[InputFieldLength] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(TextPosition > (Handle.Width - 8))
|
||||
{
|
||||
TextIndex = TextPosition - (Handle.Width - 8);
|
||||
TextCursorPosition = Handle.Width - 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
TextIndex = 0;
|
||||
TextCursorPosition = TextPosition;
|
||||
}
|
||||
|
||||
/* Redraw input field and button */
|
||||
BlpDrawDialogButton(&Handle);
|
||||
BlpDrawDialogInputField(&Handle, &InputFieldBuffer[TextIndex]);
|
||||
|
||||
if(Handle.Attributes & TUI_DIALOG_ACTIVE_INPUT_FIELD)
|
||||
{
|
||||
BlSetCursorPosition(Handle.PosX + 4 + TextCursorPosition, Handle.PosY + Handle.Height - 4);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear screen to remove dialog box */
|
||||
BlSetConsoleAttributes(EFI_TEXT_BGCOLOR_BLACK | EFI_TEXT_FGCOLOR_LIGHTGRAY);
|
||||
BlConsoleClearScreen();
|
||||
}
|
||||
|
||||
XTCDECL
|
||||
XTBL_DIALOG_HANDLE
|
||||
BlDisplayProgressDialog(IN PWCHAR Caption,
|
||||
IN PWCHAR Message,
|
||||
IN UCHAR Percentage)
|
||||
{
|
||||
XTBL_DIALOG_HANDLE Handle;
|
||||
|
||||
/* Set dialog window attributes */
|
||||
Handle.Attributes = TUI_DIALOG_GENERIC_BOX | TUI_DIALOG_PROGRESS_BAR;
|
||||
|
||||
/* Determine dialog window size and position */
|
||||
BlpDetermineDialogBoxSize(&Handle, Message);
|
||||
|
||||
/* Disable cursor and draw dialog box */
|
||||
BlConsoleDisableCursor();
|
||||
BlpDrawDialogBox(&Handle, Caption, Message);
|
||||
|
||||
/* Draw active button */
|
||||
BlpDrawDialogProgressBar(&Handle, Percentage);
|
||||
|
||||
/* Return dialog handle */
|
||||
return Handle;
|
||||
}
|
||||
|
||||
// TODO: Common routine for printing text on dialog window
|
||||
XTCDECL
|
||||
VOID
|
||||
BlUpdateProgressBar(IN PXTBL_DIALOG_HANDLE Handle,
|
||||
IN PWCHAR Message,
|
||||
IN UCHAR Percentage)
|
||||
{
|
||||
SIZE_T Index, Length;
|
||||
|
||||
/* Check if message needs an update */
|
||||
if(Message != NULL)
|
||||
{
|
||||
/* Determine message length */
|
||||
Length = RtlWideStringLength(Message, 0);
|
||||
|
||||
/* Update message in the dialog box */
|
||||
BlSetCursorPosition(Handle->PosX + 2, Handle->PosY + 2);
|
||||
BlConsolePrint(L"%S", Message);
|
||||
|
||||
if(Length < Handle->Width - 4)
|
||||
{
|
||||
for(Index = Length; Index < Handle->Width - 4; Index++)
|
||||
{
|
||||
BlConsolePrint(L" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update progress bar */
|
||||
BlpDrawDialogProgressBar(Handle, Percentage);
|
||||
}
|
Loading…
Reference in New Issue
Block a user