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