diff --git a/xtldr2/includes/bootman.h b/xtldr2/includes/bootman.h index 3d19134..0002412 100644 --- a/xtldr2/includes/bootman.h +++ b/xtldr2/includes/bootman.h @@ -60,6 +60,12 @@ VOID BlDisplayInfoDialog(IN PWCHAR Caption, IN PWCHAR Message); +XTCDECL +VOID +BlDisplayInputDialog(IN PWCHAR Caption, + IN PWCHAR Message, + IN OUT PWCHAR *InputFieldText); + XTCDECL XTBL_DIALOG_HANDLE BlDisplayProgressDialog(IN PWCHAR Caption, diff --git a/xtldr2/textui.c b/xtldr2/textui.c index 5141a33..52b5755 100644 --- a/xtldr2/textui.c +++ b/xtldr2/textui.c @@ -369,6 +369,222 @@ BlDisplayInfoDialog(IN PWCHAR Caption, BlClearConsoleScreen(); } +/** + * Displays a blue informational dialog box with the specified caption and message and an input field. + * + * @param Caption + * Specifies a caption string put on the dialog box. + * + * @param Message + * Specifies a message string put on the dialog box. + * + * @param InputFieldText + * Specifies a pointer to the input field text that will be edited. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +BlDisplayInputDialog(IN PWCHAR Caption, + IN PWCHAR Message, + IN PWCHAR *InputFieldText) +{ + SIZE_T InputFieldLength, TextCursorPosition, TextIndex, TextPosition; + XTBL_DIALOG_HANDLE Handle; + PWCHAR InputFieldBuffer; + SIZE_T BufferLength; + EFI_INPUT_KEY Key; + EFI_STATUS Status; + UINT_PTR Index; + + /* Set dialog window attributes */ + Handle.Attributes = XTBL_TUI_DIALOG_GENERIC_BOX | XTBL_TUI_DIALOG_ACTIVE_INPUT | XTBL_TUI_DIALOG_INACTIVE_BUTTON; + + /* Determine dialog window size and position */ + BlpDetermineDialogBoxSize(&Handle, Message); + + /* Disable cursor and draw dialog box */ + BlDisableConsoleCursor(); + BlpDrawDialogBox(&Handle, Caption, Message); + + /* Draw inactive button */ + BlpDrawDialogButton(&Handle); + + /* Draw active input field */ + BlpDrawDialogInputField(&Handle, *InputFieldText); + + /* Initialize key stroke */ + Key.ScanCode = 0; + Key.UnicodeChar = 0; + + /* Get initial input text length and allocate a buffer */ + BufferLength = RtlWideStringLength(*InputFieldText, 0); + Status = BlMemoryAllocatePool(BufferLength * sizeof(WCHAR), (PVOID *)&InputFieldBuffer); + if(Status != STATUS_EFI_SUCCESS) + { + /* Memory allocation failure, print error message and return */ + BlDebugPrint(L"ERROR: Memory allocation failure (Status Code: 0x%lx)\n", Status); + BlDisplayErrorDialog(L"XTLDR", L"Failed to allocate memory for input field buffer."); + return; + } + + /* Copy input text into edit buffer */ + RtlCopyMemory(InputFieldBuffer, *InputFieldText, BufferLength * sizeof(WCHAR)); + InputFieldBuffer[BufferLength] = L'\0'; + + /* Determine input field length */ + InputFieldLength = BufferLength; + 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 */ + BlWaitForEfiEvent(1, &EfiSystemTable->ConIn->WaitForKey, &Index); + BlReadKeyStroke(&Key); + BlResetConsoleInputBuffer(); + + /* 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 ^= (XTBL_TUI_DIALOG_ACTIVE_INPUT | XTBL_TUI_DIALOG_INACTIVE_INPUT); + Handle.Attributes ^= (XTBL_TUI_DIALOG_ACTIVE_BUTTON | XTBL_TUI_DIALOG_INACTIVE_BUTTON); + } + else if(Key.ScanCode == 0x03) + { + /* RIGHT key pressed, move cursor forward */ + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT && TextPosition < InputFieldLength) + { + TextPosition++; + } + } + else if(Key.ScanCode == 0x04) + { + /* LEFT key pressed, move cursor back */ + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT && TextPosition > 0) + { + TextPosition--; + } + } + else if(Key.ScanCode == 0x05) + { + /* HOME key pressed, move cursor to the beginning */ + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) + { + TextPosition = 0; + } + } + else if(Key.ScanCode == 0x06) + { + /* END key pressed, move cursor to the end */ + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) + { + TextPosition = InputFieldLength; + } + } + else if(Key.ScanCode == 0x08) + { + /* DELETE key pressed, delete character */ + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) + { + if(InputFieldLength > 0 && TextPosition < InputFieldLength) + { + RtlMoveMemory(InputFieldBuffer + TextPosition, InputFieldBuffer + TextPosition + 1, + (InputFieldLength - TextPosition) * sizeof(WCHAR)); + InputFieldLength--; + InputFieldBuffer[InputFieldLength] = 0; + } + } + } + else if(Key.UnicodeChar == 0x08) + { + /* BACKSPACE key pressed, delete character */ + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) + { + if(InputFieldLength > 0 && TextPosition > 0 && TextPosition <= InputFieldLength) + { + TextPosition--; + RtlMoveMemory(InputFieldBuffer + TextPosition, InputFieldBuffer + TextPosition + 1, + (InputFieldLength - TextPosition) * sizeof(WCHAR)); + InputFieldLength--; + InputFieldBuffer[InputFieldLength] = 0; + } + } + } + else if(Key.UnicodeChar == 0x0D) + { + /* ENTER key pressed, allocate memory for updated input text */ + BufferLength = RtlWideStringLength(InputFieldBuffer, 0); + BlMemoryFreePool(*InputFieldText); + Status = BlMemoryAllocatePool(BufferLength * sizeof(WCHAR), (PVOID *)*InputFieldText); + if(Status != STATUS_EFI_SUCCESS) + { + /* Failed to allocate memory, print error message and return status code */ + BlDebugPrint(L"ERROR: Memory allocation failure (Status Code: 0x%lx)\n", Status); + BlDisplayErrorDialog(L"XTLDR", L"Failed to save input data."); + break; + } + + /* Copy edit buffer into original buffer */ + RtlZeroMemory(InputFieldText, BufferLength * sizeof(WCHAR)); + RtlCopyMemory(*InputFieldText, InputFieldBuffer, BufferLength * sizeof(WCHAR)); + break; + } + else + { + /* Other key pressed, add character to the buffer */ + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT && Key.UnicodeChar != 0) + { + RtlMoveMemory(InputFieldBuffer + TextPosition + 1, InputFieldBuffer + TextPosition, + (InputFieldLength - TextPosition) * sizeof(WCHAR)); + InputFieldBuffer[TextPosition] = Key.UnicodeChar; + TextPosition++; + InputFieldLength++; + InputFieldBuffer[InputFieldLength] = 0; + } + } + + if(TextPosition > (Handle.Width - 9)) + { + TextIndex = TextPosition - (Handle.Width - 9); + TextCursorPosition = Handle.Width - 9; + } + else + { + TextIndex = 0; + TextCursorPosition = TextPosition; + } + + /* Redraw input field and button */ + BlpDrawDialogButton(&Handle); + BlpDrawDialogInputField(&Handle, &InputFieldBuffer[TextIndex]); + + if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) + { + 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); + BlClearConsoleScreen(); +} + /** * Displays a blue informational dialog box with the specified caption and message and a progress bar. * @@ -1060,173 +1276,3 @@ BlpDrawDialogProgressBar(IN PXTBL_DIALOG_HANDLE Handle, BlDisableConsoleCursor(); BlConsoleWrite(ProgressBar); } - - - - - - -// TODO: FIX, this is completely broken -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 = XTBL_TUI_DIALOG_GENERIC_BOX | XTBL_TUI_DIALOG_ACTIVE_INPUT | XTBL_TUI_DIALOG_INACTIVE_BUTTON; - - /* Determine dialog window size and position */ - BlpDetermineDialogBoxSize(&Handle, Message); - - /* Disable cursor and draw dialog box */ - BlDisableConsoleCursor(); - 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 */ - BlWaitForEfiEvent(1, &EfiSystemTable->ConIn->WaitForKey, &Index); - BlReadKeyStroke(&Key); - BlResetConsoleInputBuffer(); - - /* 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 ^= (XTBL_TUI_DIALOG_ACTIVE_INPUT | XTBL_TUI_DIALOG_INACTIVE_INPUT); - Handle.Attributes ^= (XTBL_TUI_DIALOG_ACTIVE_BUTTON | XTBL_TUI_DIALOG_INACTIVE_BUTTON); - } - else if(Key.ScanCode == 0x03) - { - /* RIGHT key pressed, move cursor forward */ - if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT && TextPosition < InputFieldLength) - { - TextPosition++; - } - } - else if(Key.ScanCode == 0x04) - { - /* LEFT key pressed, move cursor back */ - if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT && TextPosition > 0) - { - TextPosition--; - } - } - else if(Key.ScanCode == 0x05) - { - /* HOME key pressed, move cursor to the beginning */ - if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) - { - TextPosition = 0; - } - } - else if(Key.ScanCode == 0x06) - { - /* END key pressed, move cursor to the end */ - if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) - { - TextPosition = InputFieldLength; - } - } - else if(Key.ScanCode == 0x08) - { - /* DELETE key pressed, delete character */ - if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) - { - if(InputFieldLength > 0 && TextPosition < InputFieldLength) - { - RtlMoveMemory(InputFieldBuffer + TextPosition, InputFieldBuffer + TextPosition + 1, (InputFieldLength - TextPosition) * sizeof(WCHAR)); - InputFieldLength--; - InputFieldBuffer[InputFieldLength] = 0; - } - } - } - else if(Key.UnicodeChar == 0x08) - { - /* BACKSPACE key pressed, delete character */ - if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) - { - if(InputFieldLength > 0 && TextPosition > 0 && TextPosition <= InputFieldLength) - { - TextPosition--; - RtlMoveMemory(InputFieldBuffer + TextPosition, InputFieldBuffer + TextPosition + 1, (InputFieldLength - TextPosition) * sizeof(WCHAR)); - InputFieldLength--; - InputFieldBuffer[InputFieldLength] = 0; - } - } - } - else if(Key.UnicodeChar == 0x0D) - { - /* ENTER key pressed */ - } - else - { - /* Other key pressed, add character to the buffer */ - if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT && Key.UnicodeChar != 0) - { - RtlMoveMemory(InputFieldBuffer + TextPosition + 1, InputFieldBuffer + TextPosition, (InputFieldLength - TextPosition) * sizeof(WCHAR)); - InputFieldBuffer[TextPosition] = Key.UnicodeChar; - TextPosition++; - InputFieldLength++; - InputFieldBuffer[InputFieldLength] = 0; - } - } - - if(TextPosition > (Handle.Width - 9)) - { - TextIndex = TextPosition - (Handle.Width - 9); - TextCursorPosition = Handle.Width - 9; - } - else - { - TextIndex = 0; - TextCursorPosition = TextPosition; - } - - /* Redraw input field and button */ - BlpDrawDialogButton(&Handle); - BlpDrawDialogInputField(&Handle, &InputFieldBuffer[TextIndex]); - - if(Handle.Attributes & XTBL_TUI_DIALOG_ACTIVE_INPUT) - { - 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); - BlClearConsoleScreen(); -}