ShellPkg/[hex]edit: use SimpleTextInEx to read console
[mirror_edk2.git] / ShellPkg / Library / UefiShellDebug1CommandsLib / EditInputBar.c
1 /** @file
2 Implements inputbar interface functions.
3
4 Copyright (c) 2005 - 2018, 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 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *mTextInEx;
22
23 /**
24 Initialize the input bar.
25
26 @param[in] TextInEx Pointer to SimpleTextInEx instance in System Table.
27 **/
28 VOID
29 InputBarInit (
30 IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInEx
31 )
32 {
33 mPrompt = NULL;
34 mReturnString = NULL;
35 StringSize = 0;
36 mTextInEx = TextInEx;
37 }
38
39 /**
40 Cleanup function for input bar.
41 **/
42 VOID
43 InputBarCleanup (
44 VOID
45 )
46 {
47 //
48 // free input bar's prompt and input string
49 //
50 SHELL_FREE_NON_NULL (mPrompt);
51 SHELL_FREE_NON_NULL (mReturnString);
52 mPrompt = NULL;
53 mReturnString = NULL;
54 }
55
56 /**
57 Display the prompt.
58 Do the requesting of input.
59
60 @param[in] LastColumn The last printable column.
61 @param[in] LastRow The last printable row.
62 **/
63 VOID
64 InputBarPrintInput (
65 IN UINTN LastColumn,
66 IN UINTN LastRow
67 )
68 {
69 UINTN Limit;
70 UINTN Size;
71 CHAR16 *Buffer;
72 UINTN Index;
73 UINTN mPromptLen;
74
75 mPromptLen = StrLen (mPrompt);
76 Limit = LastColumn - mPromptLen - 1;
77 Size = StrLen (mReturnString);
78
79 //
80 // check whether the mPrompt length and input length will
81 // exceed limit
82 //
83 if (Size <= Limit) {
84 Buffer = mReturnString;
85 } else {
86 Buffer = mReturnString + Size - Limit;
87 }
88
89 gST->ConOut->EnableCursor (gST->ConOut, FALSE);
90
91 ShellPrintEx (((INT32)mPromptLen), ((INT32)LastRow) - 1, L"%s", Buffer);
92 Size = StrLen (Buffer);
93
94 //
95 // print " " after mPrompt
96 //
97 for (Index = Size; Index < Limit; Index++) {
98 ShellPrintEx ((INT32)(mPromptLen + Size), ((INT32)LastRow) - 1, L" ");
99 }
100
101 gST->ConOut->EnableCursor (gST->ConOut, TRUE);
102 gST->ConOut->SetCursorPosition (gST->ConOut, Size + mPromptLen, LastRow - 1);
103 }
104
105 typedef struct {
106 UINT32 Foreground : 4;
107 UINT32 Background : 3;
108 } INPUT_BAR_COLOR_ATTRIBUTES;
109
110 typedef union {
111 INPUT_BAR_COLOR_ATTRIBUTES Colors;
112 UINTN Data;
113 } INPUT_BAR_COLOR_UNION;
114
115
116 /**
117 The refresh function for InputBar, it will wait for user input
118
119 @param[in] LastRow The last printable row.
120 @param[in] LastColumn The last printable column.
121
122 @retval EFI_SUCCESS The operation was successful.
123 **/
124 EFI_STATUS
125 InputBarRefresh (
126 UINTN LastRow,
127 UINTN LastColumn
128 )
129 {
130 INPUT_BAR_COLOR_UNION Orig;
131 INPUT_BAR_COLOR_UNION New;
132 EFI_KEY_DATA KeyData;
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 Status = gBS->WaitForEvent (1, &mTextInEx->WaitForKeyEx, &EventIndex);
182 if (EFI_ERROR (Status) || (EventIndex != 0)) {
183 continue;
184 }
185 Status = mTextInEx->ReadKeyStrokeEx (mTextInEx, &KeyData);
186 if (EFI_ERROR (Status)) {
187 continue;
188 }
189 if (((KeyData.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) != 0) &&
190 (KeyData.KeyState.KeyShiftState != EFI_SHIFT_STATE_VALID)) {
191 //
192 // Shift key pressed.
193 //
194 continue;
195 }
196 //
197 // pressed ESC
198 //
199 if (KeyData.Key.ScanCode == SCAN_ESC) {
200 Size = 0;
201 Status = EFI_NOT_READY;
202 break;
203 }
204 //
205 // return pressed
206 //
207 if (KeyData.Key.UnicodeChar == CHAR_LINEFEED || KeyData.Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
208 break;
209 } else if (KeyData.Key.UnicodeChar == CHAR_BACKSPACE) {
210 //
211 // backspace
212 //
213 if (Size > 0) {
214 Size--;
215 mReturnString[Size] = CHAR_NULL;
216 if (!NoDisplay) {
217
218 InputBarPrintInput (LastColumn, LastRow);
219
220 }
221 }
222 } else if (KeyData.Key.UnicodeChar <= 127 && KeyData.Key.UnicodeChar >= 32) {
223 //
224 // VALID ASCII char pressed
225 //
226 mReturnString[Size] = KeyData.Key.UnicodeChar;
227
228 //
229 // should be less than specified length
230 //
231 if (Size >= StringSize) {
232 continue;
233 }
234
235 Size++;
236
237 mReturnString[Size] = CHAR_NULL;
238
239 if (!NoDisplay) {
240
241 InputBarPrintInput (LastColumn, LastRow);
242
243 } else {
244 //
245 // if just choose yes/no
246 //
247 break;
248 }
249
250 }
251 }
252
253 mReturnString[Size] = CHAR_NULL;
254
255
256 //
257 // restore screen attributes
258 //
259 gST->ConOut->SetCursorPosition (gST->ConOut, CursorCol, CursorRow);
260 gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
261
262 return Status;
263 }
264
265 /**
266 SetPrompt and wait for input.
267
268 @param[in] Str The prompt string.
269
270 @retval EFI_SUCCESS The operation was successful.
271 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
272 **/
273 EFI_STATUS
274 InputBarSetPrompt (
275 IN CONST CHAR16 *Str
276 )
277 {
278 //
279 // FREE the old mPrompt string
280 //
281 SHELL_FREE_NON_NULL (mPrompt);
282
283 mPrompt = CatSPrint (NULL, L"%s ", Str);
284 if (mPrompt == NULL) {
285 return EFI_OUT_OF_RESOURCES;
286 }
287
288 return EFI_SUCCESS;
289 }
290
291 /**
292 Set the size of the string in characters.
293
294 @param[in] Size The max number of characters to accept.
295
296 @retval EFI_SUCCESS The operation was successful.
297 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
298 **/
299 EFI_STATUS
300 InputBarSetStringSize (
301 UINTN Size
302 )
303 {
304 //
305 // free the old ReturnStirng
306 //
307 SHELL_FREE_NON_NULL (mReturnString);
308
309 StringSize = Size;
310 mReturnString = AllocateZeroPool ((StringSize + 1) * sizeof(mReturnString[0]));
311 if (mReturnString == NULL) {
312 return EFI_OUT_OF_RESOURCES;
313 }
314
315 return EFI_SUCCESS;
316 }
317
318 /**
319 Function to retrieve the input from the user.
320
321 @retval NULL No input has been received.
322 @return The string that was input.
323 **/
324 CONST CHAR16*
325 InputBarGetString (
326 VOID
327 )
328 {
329 return (mReturnString);
330 }