| /** @file | |
| Implements inputbar interface functions. | |
| Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include "EditInputBar.h" | |
| #include "UefiShellDebug1CommandsLib.h" | |
| CHAR16 *mPrompt; // Input bar mPrompt string. | |
| CHAR16 *mReturnString; // The returned string. | |
| UINTN StringSize; // Size of mReturnString space size. | |
| EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *mTextInEx; | |
| /** | |
| Initialize the input bar. | |
| @param[in] TextInEx Pointer to SimpleTextInEx instance in System Table. | |
| **/ | |
| VOID | |
| InputBarInit ( | |
| IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx | |
| ) | |
| { | |
| mPrompt = NULL; | |
| mReturnString = NULL; | |
| StringSize = 0; | |
| mTextInEx = TextInEx; | |
| } | |
| /** | |
| Cleanup function for input bar. | |
| **/ | |
| VOID | |
| InputBarCleanup ( | |
| VOID | |
| ) | |
| { | |
| // | |
| // free input bar's prompt and input string | |
| // | |
| SHELL_FREE_NON_NULL (mPrompt); | |
| SHELL_FREE_NON_NULL (mReturnString); | |
| mPrompt = NULL; | |
| mReturnString = NULL; | |
| } | |
| /** | |
| Display the prompt. | |
| Do the requesting of input. | |
| @param[in] LastColumn The last printable column. | |
| @param[in] LastRow The last printable row. | |
| **/ | |
| VOID | |
| InputBarPrintInput ( | |
| IN UINTN LastColumn, | |
| IN UINTN LastRow | |
| ) | |
| { | |
| UINTN Limit; | |
| UINTN Size; | |
| CHAR16 *Buffer; | |
| UINTN Index; | |
| UINTN mPromptLen; | |
| mPromptLen = StrLen (mPrompt); | |
| Limit = LastColumn - mPromptLen - 1; | |
| Size = StrLen (mReturnString); | |
| // | |
| // check whether the mPrompt length and input length will | |
| // exceed limit | |
| // | |
| if (Size <= Limit) { | |
| Buffer = mReturnString; | |
| } else { | |
| Buffer = mReturnString + Size - Limit; | |
| } | |
| gST->ConOut->EnableCursor (gST->ConOut, FALSE); | |
| ShellPrintEx (((INT32)mPromptLen), ((INT32)LastRow) - 1, L"%s", Buffer); | |
| Size = StrLen (Buffer); | |
| // | |
| // print " " after mPrompt | |
| // | |
| for (Index = Size; Index < Limit; Index++) { | |
| ShellPrintEx ((INT32)(mPromptLen + Size), ((INT32)LastRow) - 1, L" "); | |
| } | |
| gST->ConOut->EnableCursor (gST->ConOut, TRUE); | |
| gST->ConOut->SetCursorPosition (gST->ConOut, Size + mPromptLen, LastRow - 1); | |
| } | |
| typedef struct { | |
| UINT32 Foreground : 4; | |
| UINT32 Background : 3; | |
| } INPUT_BAR_COLOR_ATTRIBUTES; | |
| typedef union { | |
| INPUT_BAR_COLOR_ATTRIBUTES Colors; | |
| UINTN Data; | |
| } INPUT_BAR_COLOR_UNION; | |
| /** | |
| The refresh function for InputBar, it will wait for user input | |
| @param[in] LastRow The last printable row. | |
| @param[in] LastColumn The last printable column. | |
| @retval EFI_SUCCESS The operation was successful. | |
| **/ | |
| EFI_STATUS | |
| InputBarRefresh ( | |
| UINTN LastRow, | |
| UINTN LastColumn | |
| ) | |
| { | |
| INPUT_BAR_COLOR_UNION Orig; | |
| INPUT_BAR_COLOR_UNION New; | |
| EFI_KEY_DATA KeyData; | |
| UINTN Size; | |
| EFI_STATUS Status; | |
| BOOLEAN NoDisplay; | |
| UINTN EventIndex; | |
| UINTN CursorRow; | |
| UINTN CursorCol; | |
| // | |
| // variable initialization | |
| // | |
| Size = 0; | |
| Status = EFI_SUCCESS; | |
| // | |
| // back up the old screen attributes | |
| // | |
| CursorCol = gST->ConOut->Mode->CursorColumn; | |
| CursorRow = gST->ConOut->Mode->CursorRow; | |
| Orig.Data = gST->ConOut->Mode->Attribute; | |
| New.Data = 0; | |
| New.Colors.Foreground = Orig.Colors.Background & 0xF; | |
| New.Colors.Background = Orig.Colors.Foreground & 0x7; | |
| gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F); | |
| // | |
| // clear input bar | |
| // | |
| EditorClearLine (LastRow, LastColumn, LastRow); | |
| gST->ConOut->SetCursorPosition (gST->ConOut, 0, LastRow - 1); | |
| ShellPrintHiiDefaultEx (STRING_TOKEN (STR_EDIT_LIBINPUTBAR_MAININPUTBAR), gShellDebug1HiiHandle, mPrompt); | |
| // | |
| // this is a selection mPrompt, cursor will stay in edit area | |
| // actually this is for search , search/replace | |
| // | |
| if (StrStr (mPrompt, L"Yes/No")) { | |
| NoDisplay = TRUE; | |
| gST->ConOut->SetCursorPosition (gST->ConOut, CursorCol, CursorRow); | |
| gST->ConOut->SetAttribute (gST->ConOut, Orig.Data); | |
| } else { | |
| NoDisplay = FALSE; | |
| } | |
| // | |
| // wait for user input | |
| // | |
| for ( ; ;) { | |
| Status = gBS->WaitForEvent (1, &mTextInEx->WaitForKeyEx, &EventIndex); | |
| if (EFI_ERROR (Status) || (EventIndex != 0)) { | |
| continue; | |
| } | |
| Status = mTextInEx->ReadKeyStrokeEx (mTextInEx, &KeyData); | |
| if (EFI_ERROR (Status)) { | |
| continue; | |
| } | |
| if (((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) && | |
| (KeyData.KeyState.KeyShiftState != EFI_SHIFT_STATE_VALID)) | |
| { | |
| // | |
| // Shift key pressed. | |
| // | |
| continue; | |
| } | |
| // | |
| // pressed ESC | |
| // | |
| if (KeyData.Key.ScanCode == SCAN_ESC) { | |
| Size = 0; | |
| Status = EFI_NOT_READY; | |
| break; | |
| } | |
| // | |
| // return pressed | |
| // | |
| if ((KeyData.Key.UnicodeChar == CHAR_LINEFEED) || (KeyData.Key.UnicodeChar == CHAR_CARRIAGE_RETURN)) { | |
| break; | |
| } else if (KeyData.Key.UnicodeChar == CHAR_BACKSPACE) { | |
| // | |
| // backspace | |
| // | |
| if (Size > 0) { | |
| Size--; | |
| mReturnString[Size] = CHAR_NULL; | |
| if (!NoDisplay) { | |
| InputBarPrintInput (LastColumn, LastRow); | |
| } | |
| } | |
| } else if ((KeyData.Key.UnicodeChar <= 127) && (KeyData.Key.UnicodeChar >= 32)) { | |
| // | |
| // VALID ASCII char pressed | |
| // | |
| mReturnString[Size] = KeyData.Key.UnicodeChar; | |
| // | |
| // should be less than specified length | |
| // | |
| if (Size >= StringSize) { | |
| continue; | |
| } | |
| Size++; | |
| mReturnString[Size] = CHAR_NULL; | |
| if (!NoDisplay) { | |
| InputBarPrintInput (LastColumn, LastRow); | |
| } else { | |
| // | |
| // if just choose yes/no | |
| // | |
| break; | |
| } | |
| } | |
| } | |
| mReturnString[Size] = CHAR_NULL; | |
| // | |
| // restore screen attributes | |
| // | |
| gST->ConOut->SetCursorPosition (gST->ConOut, CursorCol, CursorRow); | |
| gST->ConOut->SetAttribute (gST->ConOut, Orig.Data); | |
| return Status; | |
| } | |
| /** | |
| SetPrompt and wait for input. | |
| @param[in] Str The prompt string. | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_OUT_OF_RESOURCES A memory allocation failed. | |
| **/ | |
| EFI_STATUS | |
| InputBarSetPrompt ( | |
| IN CONST CHAR16 *Str | |
| ) | |
| { | |
| // | |
| // FREE the old mPrompt string | |
| // | |
| SHELL_FREE_NON_NULL (mPrompt); | |
| mPrompt = CatSPrint (NULL, L"%s ", Str); | |
| if (mPrompt == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Set the size of the string in characters. | |
| @param[in] Size The max number of characters to accept. | |
| @retval EFI_SUCCESS The operation was successful. | |
| @retval EFI_OUT_OF_RESOURCES A memory allocation failed. | |
| **/ | |
| EFI_STATUS | |
| InputBarSetStringSize ( | |
| UINTN Size | |
| ) | |
| { | |
| // | |
| // free the old ReturnStirng | |
| // | |
| SHELL_FREE_NON_NULL (mReturnString); | |
| StringSize = Size; | |
| mReturnString = AllocateZeroPool ((StringSize + 1) * sizeof (mReturnString[0])); | |
| if (mReturnString == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Function to retrieve the input from the user. | |
| @retval NULL No input has been received. | |
| @return The string that was input. | |
| **/ | |
| CONST CHAR16 * | |
| InputBarGetString ( | |
| VOID | |
| ) | |
| { | |
| return (mReturnString); | |
| } |