/** @file Implements inputbar interface functions. Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.
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); ShellPrintHiiEx (-1, -1, NULL, 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); }