1 /** @file
2   Implements inputbar interface functions.
3 
4   Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved. <BR>
5   This program and the accompanying materials
6   are licensed and made available under the terms and conditions of the BSD License
7   which accompanies this distribution.  The full text of the license may be found at
8   http://opensource.org/licenses/bsd-license.php
9 
10   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12 
13 **/
14 
15 #include "EditInputBar.h"
16 #include "UefiShellDebug1CommandsLib.h"
17 
18 CHAR16  *mPrompt;        // Input bar mPrompt string.
19 CHAR16  *mReturnString;  // The returned string.
20 UINTN   StringSize;      // Size of mReturnString space size.
21 
22 /**
23   Initialize the input bar.
24 **/
25 VOID
InputBarInit(VOID)26 InputBarInit (
27   VOID
28   )
29 {
30   mPrompt       = NULL;
31   mReturnString = NULL;
32   StringSize    = 0;
33 }
34 
35 /**
36   Cleanup function for input bar.
37 **/
38 VOID
InputBarCleanup(VOID)39 InputBarCleanup (
40   VOID
41   )
42 {
43   //
44   // free input bar's prompt and input string
45   //
46   SHELL_FREE_NON_NULL (mPrompt);
47   SHELL_FREE_NON_NULL (mReturnString);
48   mPrompt       = NULL;
49   mReturnString = NULL;
50 }
51 
52 /**
53   Display the prompt.
54   Do the requesting of input.
55 
56   @param[in]  LastColumn   The last printable column.
57   @param[in]  LastRow      The last printable row.
58 **/
59 VOID
InputBarPrintInput(IN UINTN LastColumn,IN UINTN LastRow)60 InputBarPrintInput (
61   IN UINTN LastColumn,
62   IN UINTN LastRow
63   )
64 {
65   UINTN   Limit;
66   UINTN   Size;
67   CHAR16  *Buffer;
68   UINTN   Index;
69   UINTN   mPromptLen;
70 
71   mPromptLen = StrLen (mPrompt);
72   Limit     = LastColumn - mPromptLen - 1;
73   Size      = StrLen (mReturnString);
74 
75   //
76   // check whether the mPrompt length and input length will
77   // exceed limit
78   //
79   if (Size <= Limit) {
80     Buffer = mReturnString;
81   } else {
82     Buffer = mReturnString + Size - Limit;
83   }
84 
85   gST->ConOut->EnableCursor (gST->ConOut, FALSE);
86 
87   ShellPrintEx (((INT32)mPromptLen), ((INT32)LastRow) - 1, L"%s", Buffer);
88   Size = StrLen (Buffer);
89 
90   //
91   // print " " after mPrompt
92   //
93   for (Index = Size; Index < Limit; Index++) {
94     ShellPrintEx ((INT32)(mPromptLen + Size), ((INT32)LastRow) - 1, L" ");
95   }
96 
97   gST->ConOut->EnableCursor (gST->ConOut, TRUE);
98   gST->ConOut->SetCursorPosition (gST->ConOut, Size + mPromptLen, LastRow - 1);
99 }
100 
101 typedef struct {
102   UINT32  Foreground : 4;
103   UINT32  Background : 3;
104 } INPUT_BAR_COLOR_ATTRIBUTES;
105 
106 typedef union {
107   INPUT_BAR_COLOR_ATTRIBUTES  Colors;
108   UINTN                       Data;
109 } INPUT_BAR_COLOR_UNION;
110 
111 
112 /**
113   The refresh function for InputBar, it will wait for user input
114 
115   @param[in] LastRow            The last printable row.
116   @param[in] LastColumn         The last printable column.
117 
118   @retval EFI_SUCCESS           The operation was successful.
119 **/
120 EFI_STATUS
InputBarRefresh(UINTN LastRow,UINTN LastColumn)121 InputBarRefresh (
122   UINTN LastRow,
123   UINTN LastColumn
124   )
125 {
126   INPUT_BAR_COLOR_UNION   Orig;
127   INPUT_BAR_COLOR_UNION   New;
128   EFI_INPUT_KEY           Key;
129   UINTN                   Size;
130   EFI_STATUS              Status;
131   BOOLEAN                 NoDisplay;
132   UINTN                   EventIndex;
133   UINTN                   CursorRow;
134   UINTN                   CursorCol;
135 
136   //
137   // variable initialization
138   //
139   Size    = 0;
140   Status  = EFI_SUCCESS;
141 
142   //
143   // back up the old screen attributes
144   //
145   CursorCol             = gST->ConOut->Mode->CursorColumn;
146   CursorRow             = gST->ConOut->Mode->CursorRow;
147   Orig.Data             = gST->ConOut->Mode->Attribute;
148   New.Data              = 0;
149   New.Colors.Foreground = Orig.Colors.Background & 0xF;
150   New.Colors.Background = Orig.Colors.Foreground & 0x7;
151 
152   gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
153 
154   //
155   // clear input bar
156   //
157   EditorClearLine (LastRow , LastColumn, LastRow);
158 
159   gST->ConOut->SetCursorPosition (gST->ConOut, 0, LastRow - 1);
160   ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBINPUTBAR_MAININPUTBAR), gShellDebug1HiiHandle, mPrompt);
161 
162   //
163   // this is a selection mPrompt, cursor will stay in edit area
164   // actually this is for search , search/replace
165   //
166   if (StrStr (mPrompt, L"Yes/No")) {
167     NoDisplay = TRUE;
168     gST->ConOut->SetCursorPosition (gST->ConOut, CursorCol, CursorRow);
169     gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
170   } else {
171     NoDisplay = FALSE;
172   }
173   //
174   // wait for user input
175   //
176   for (;;) {
177     gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
178     Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
179     if (EFI_ERROR (Status)) {
180       continue;
181     }
182     //
183     // pressed ESC
184     //
185     if (Key.ScanCode == SCAN_ESC) {
186       Size    = 0;
187       Status  = EFI_NOT_READY;
188       break;
189     }
190     //
191     // return pressed
192     //
193     if (Key.UnicodeChar == CHAR_LINEFEED || Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
194       break;
195     } else if (Key.UnicodeChar == CHAR_BACKSPACE) {
196       //
197       // backspace
198       //
199       if (Size > 0) {
200         Size--;
201         mReturnString[Size] = CHAR_NULL;
202         if (!NoDisplay) {
203 
204           InputBarPrintInput (LastColumn, LastRow);
205 
206         }
207       }
208     } else if (Key.UnicodeChar <= 127 && Key.UnicodeChar >= 32) {
209       //
210       // VALID ASCII char pressed
211       //
212       mReturnString[Size] = Key.UnicodeChar;
213 
214       //
215       // should be less than specified length
216       //
217       if (Size >= StringSize) {
218         continue;
219       }
220 
221       Size++;
222 
223       mReturnString[Size] = CHAR_NULL;
224 
225       if (!NoDisplay) {
226 
227         InputBarPrintInput (LastColumn, LastRow);
228 
229       } else {
230         //
231         // if just choose yes/no
232         //
233         break;
234       }
235 
236     }
237   }
238 
239   mReturnString[Size] = CHAR_NULL;
240 
241 
242   //
243   // restore screen attributes
244   //
245   gST->ConOut->SetCursorPosition (gST->ConOut, CursorCol, CursorRow);
246   gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
247 
248   return Status;
249 }
250 
251 /**
252   SetPrompt and wait for input.
253 
254   @param[in] Str                The prompt string.
255 
256   @retval EFI_SUCCESS           The operation was successful.
257   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
258 **/
259 EFI_STATUS
InputBarSetPrompt(IN CONST CHAR16 * Str)260 InputBarSetPrompt (
261   IN CONST CHAR16 *Str
262   )
263 {
264   //
265   // FREE the old mPrompt string
266   //
267   SHELL_FREE_NON_NULL (mPrompt);
268 
269   mPrompt = CatSPrint (NULL, L"%s ", Str);
270   if (mPrompt == NULL) {
271     return EFI_OUT_OF_RESOURCES;
272   }
273 
274   return EFI_SUCCESS;
275 }
276 
277 /**
278   Set the size of the string in characters.
279 
280   @param[in] Size               The max number of characters to accept.
281 
282   @retval EFI_SUCCESS           The operation was successful.
283   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.
284 **/
285 EFI_STATUS
InputBarSetStringSize(UINTN Size)286 InputBarSetStringSize (
287   UINTN   Size
288   )
289 {
290   //
291   // free the old ReturnStirng
292   //
293   SHELL_FREE_NON_NULL (mReturnString);
294 
295   StringSize = Size;
296   mReturnString = AllocateZeroPool ((StringSize + 1) * sizeof(mReturnString[0]));
297   if (mReturnString == NULL) {
298     return EFI_OUT_OF_RESOURCES;
299   }
300 
301   return EFI_SUCCESS;
302 }
303 
304 /**
305   Function to retrieve the input from the user.
306 
307   @retval NULL                  No input has been received.
308   @return The string that was input.
309 **/
310 CONST CHAR16*
InputBarGetString(VOID)311 InputBarGetString (
312   VOID
313   )
314 {
315   return (mReturnString);
316 }
317