]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/DisplayEngineDxe/Popup.c
MdeModulePkg/DisplayEngineDxe: Remove unnecessary parentheses in 'if'
[mirror_edk2.git] / MdeModulePkg / Universal / DisplayEngineDxe / Popup.c
CommitLineData
06aad9a2
DB
1/** @file\r
2Implementation for Hii Popup Protocol.\r
3\r
4Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "FormDisplay.h"\r
16\r
17EFI_SCREEN_DESCRIPTOR gPopupDimensions;\r
18LIST_ENTRY gUserSelectableOptions;\r
19EFI_STRING gMessageString;\r
20UINTN gMesStrLineNum;\r
21UINTN gMaxRowWidth;\r
22\r
23/**\r
24 Free the user selectable option structure data.\r
25\r
26 @param OptionList Point to the selectable option list which need to be freed.\r
27\r
28**/\r
29VOID\r
30FreeSelectableOptions(\r
31 LIST_ENTRY *OptionList\r
32 )\r
33{\r
34 LIST_ENTRY *Link;\r
35 USER_SELECTABLE_OPTION *SelectableOption;\r
36\r
37 while (!IsListEmpty (OptionList)) {\r
38 Link = GetFirstNode (OptionList);\r
39 SelectableOption = SELECTABLE_OPTION_FROM_LINK (Link);\r
40 RemoveEntryList (&SelectableOption->Link);\r
41 FreePool (SelectableOption);\r
42 }\r
43}\r
44\r
45/**\r
46 Display one selectable option.\r
47\r
48 @param SelectableOption The selectable option need to be drew.\r
49 @param Highlight Whether the option need to be highlighted.\r
50\r
51**/\r
52VOID\r
53DisplayOneSelectableOption(\r
54 IN USER_SELECTABLE_OPTION *SelectableOption,\r
55 IN BOOLEAN Highlight\r
56 )\r
57{\r
58 if (Highlight) {\r
59 gST->ConOut->SetAttribute (gST->ConOut, GetHighlightTextColor ());\r
60 }\r
61 PrintStringAt (SelectableOption->OptionCol, SelectableOption->OptionRow, SelectableOption->OptionString);\r
62 gST->ConOut->SetAttribute (gST->ConOut, GetPopupColor ());\r
63}\r
64\r
65/**\r
66 Add one selectable option to option list. This is the work function for AddUserSelectableOptions.\r
67\r
68 @param PopupType The option need to be drew.\r
69 @param OptionType The type of this selection option.\r
70 @param OptionString Point to the option string that to be shown.\r
71 @param OptionCol The column that the option need to be drew at.\r
72 @param OptionRow The row that the option need to be drew at.\r
73\r
74 @retval EFI_SUCCESS This function implement successfully.\r
75 @retval EFI_OUT_OF_RESOURCES There are not enough resources available.\r
76\r
77**/\r
78EFI_STATUS\r
79AddOneSelectableOption (\r
80 IN EFI_HII_POPUP_TYPE PopupType,\r
81 IN EFI_HII_POPUP_SELECTION OptionType,\r
82 IN CHAR16 *OptionString,\r
83 IN UINTN OptionCol,\r
84 IN UINTN OptionRow\r
85 )\r
86{\r
87 USER_SELECTABLE_OPTION *UserSelectableOption;\r
88\r
89 UserSelectableOption = AllocateZeroPool (sizeof (USER_SELECTABLE_OPTION));\r
90 if (UserSelectableOption == NULL) {\r
91 return EFI_OUT_OF_RESOURCES;\r
92 }\r
93 //\r
94 // Initialize the user selectable option based on the PopupType and OptionType.\r
95 // And then add the option to the option list gUserSelectableOptions.\r
96 //\r
97 UserSelectableOption->Signature = USER_SELECTABLE_OPTION_SIGNATURE;\r
98 UserSelectableOption->OptionString = OptionString;\r
99 UserSelectableOption->OptionType = OptionType;\r
100 UserSelectableOption->OptionCol = OptionCol;\r
101 UserSelectableOption->OptionRow = OptionRow;\r
102 UserSelectableOption->MinSequence = 0;\r
103\r
104 switch (PopupType) {\r
105 case EfiHiiPopupTypeOk:\r
106 UserSelectableOption->MaxSequence = 0;\r
107 UserSelectableOption->Sequence= 0;\r
108 break;\r
109 case EfiHiiPopupTypeOkCancel:\r
110 UserSelectableOption->MaxSequence = 1;\r
111 if (OptionType == EfiHiiPopupSelectionOk) {\r
112 UserSelectableOption->Sequence= 0;\r
113 } else {\r
114 UserSelectableOption->Sequence= 1;\r
115 }\r
116 break;\r
117 case EfiHiiPopupTypeYesNo:\r
118 UserSelectableOption->MaxSequence = 1;\r
119 if (OptionType == EfiHiiPopupSelectionYes) {\r
120 UserSelectableOption->Sequence = 0;\r
121 } else {\r
122 UserSelectableOption->Sequence = 1;\r
123 }\r
124 break;\r
125 case EfiHiiPopupTypeYesNoCancel:\r
126 UserSelectableOption->MaxSequence = 2;\r
127 if (OptionType == EfiHiiPopupSelectionYes) {\r
128 UserSelectableOption->Sequence = 0;\r
129 } else if (OptionType == EfiHiiPopupSelectionNo){\r
130 UserSelectableOption->Sequence = 1;\r
131 } else {\r
132 UserSelectableOption->Sequence = 2;\r
133 }\r
134 break;\r
135 default:\r
136 break;\r
137 }\r
138 InsertTailList (&gUserSelectableOptions, &UserSelectableOption->Link);\r
139\r
140 return EFI_SUCCESS;\r
141}\r
142\r
143/**\r
144 Add user selectable options to option list for different types of Popup.\r
145\r
146 @param PopupType Type of the popup to display.\r
147\r
148 @retval EFI_SUCCESS This function implement successfully.\r
149 @retval EFI_OUT_OF_RESOURCES There are not enough resources available.\r
150\r
151**/\r
152EFI_STATUS\r
153AddUserSelectableOptions (\r
154 IN EFI_HII_POPUP_TYPE PopupType\r
155 )\r
156{\r
157 EFI_STATUS Status;\r
158 UINTN EndCol;\r
159 UINTN StartCol;\r
160 UINTN OptionCol;\r
161 UINTN OptionRow;\r
162 UINTN ColDimension;\r
163\r
164 Status = EFI_SUCCESS;\r
165 EndCol = gPopupDimensions.RightColumn;\r
166 StartCol = gPopupDimensions.LeftColumn;\r
167 OptionRow = gPopupDimensions.BottomRow - POPUP_BORDER;\r
168 ColDimension = EndCol - StartCol + 1;\r
169\r
170 InitializeListHead (&gUserSelectableOptions);\r
171\r
172 switch (PopupType) {\r
173 case EfiHiiPopupTypeOk:\r
174 //\r
175 // Add [Ok] option to the option list.\r
176 //\r
177 OptionCol = StartCol + (ColDimension - USER_SELECTABLE_OPTION_OK_WIDTH) / 2;\r
178 Status = AddOneSelectableOption (PopupType, EfiHiiPopupSelectionOk, gOkOption, OptionCol, OptionRow);\r
179 break;\r
180 case EfiHiiPopupTypeOkCancel:\r
181 //\r
182 // Add [Ok] and [Cancel] options to the option list.\r
183 //\r
184 OptionCol = StartCol + (ColDimension - USER_SELECTABLE_OPTION_OK_CAL_WIDTH) / 3;\r
185 Status = AddOneSelectableOption (PopupType, EfiHiiPopupSelectionOk, gOkOption, OptionCol, OptionRow);\r
186 OptionCol = EndCol - (ColDimension - USER_SELECTABLE_OPTION_OK_CAL_WIDTH) / 3 - (GetStringWidth (gCancelOption) -2) / 2 + 1;\r
187 Status = AddOneSelectableOption (PopupType, EfiHiiPopupSelectionCancel, gCancelOption, OptionCol, OptionRow);\r
188 break;\r
189 case EfiHiiPopupTypeYesNo:\r
190 //\r
191 // Add [Yes] and [No] options to the option list.\r
192 //\r
193 OptionCol = StartCol + (ColDimension - USER_SELECTABLE_OPTION_YES_NO_WIDTH) / 3;\r
194 Status = AddOneSelectableOption (PopupType, EfiHiiPopupSelectionYes, gYesOption, OptionCol, OptionRow);\r
195 OptionCol = EndCol - (ColDimension - USER_SELECTABLE_OPTION_YES_NO_WIDTH) / 3 - (GetStringWidth (gNoOption)- 2) / 2 + 1;\r
196 Status = AddOneSelectableOption (PopupType, EfiHiiPopupSelectionNo, gNoOption, OptionCol, OptionRow);\r
197 break;\r
198 case EfiHiiPopupTypeYesNoCancel:\r
199 //\r
200 // Add [Yes], [No] and [Cancel] options to the option list.\r
201 //\r
202 OptionCol = StartCol + (ColDimension - USER_SELECTABLE_OPTION_YES_NO_CAL_WIDTH) / 4;\r
203 Status = AddOneSelectableOption (PopupType, EfiHiiPopupSelectionYes, gYesOption, OptionCol, OptionRow);\r
204 OptionCol = StartCol + (ColDimension - (GetStringWidth (gNoOption) -2) / 2) / 2;\r
205 Status = AddOneSelectableOption (PopupType, EfiHiiPopupSelectionNo, gNoOption, OptionCol, OptionRow);\r
206 OptionCol = EndCol - (ColDimension - USER_SELECTABLE_OPTION_YES_NO_CAL_WIDTH) / 4 - (GetStringWidth (gCancelOption) - 2) / 2 + 1;\r
207 Status = AddOneSelectableOption (PopupType, EfiHiiPopupSelectionCancel, gCancelOption, OptionCol, OptionRow);\r
208 break;\r
209 default:\r
210 break;\r
211 }\r
212 return Status;\r
213}\r
214\r
215/**\r
216 Show selectable options to user and get the one that user select.\r
217\r
218 @param PopupType Type of the popup to display.\r
219 @param UserSelection User selection.\r
220\r
221**/\r
222VOID\r
223GetUserSelection (\r
224 IN EFI_HII_POPUP_TYPE PopupType,\r
225 OUT EFI_HII_POPUP_SELECTION *UserSelection\r
226 )\r
227{\r
228 LIST_ENTRY *HighlightPos;\r
229 LIST_ENTRY *Link;\r
230 USER_SELECTABLE_OPTION *SelectableOption;\r
231 USER_SELECTABLE_OPTION *HighlightOption;\r
232 EFI_INPUT_KEY KeyValue;\r
233 EFI_STATUS Status;\r
234\r
235 //\r
236 // Display user selectable options in gUserSelectableOptions and get the option which user selects.\r
237 //\r
238 HighlightPos = gUserSelectableOptions.ForwardLink;\r
239 do {\r
240 for (Link = gUserSelectableOptions.ForwardLink; Link != &gUserSelectableOptions; Link = Link->ForwardLink) {\r
241 SelectableOption = SELECTABLE_OPTION_FROM_LINK (Link);\r
242 DisplayOneSelectableOption (SelectableOption, (BOOLEAN)(Link == HighlightPos));\r
243 }\r
244 //\r
245 //If UserSelection is NULL, there is no need to handle the key user input, just return.\r
246 //\r
247 if (UserSelection == NULL) {\r
248 return;\r
249 }\r
250\r
251 Status = WaitForKeyStroke (&KeyValue);\r
252 ASSERT_EFI_ERROR (Status);\r
253\r
254 HighlightOption = SELECTABLE_OPTION_FROM_LINK (HighlightPos);\r
255 switch (KeyValue.UnicodeChar) {\r
256 case CHAR_NULL:\r
257 switch (KeyValue.ScanCode) {\r
258 case SCAN_RIGHT:\r
259 if (HighlightOption->Sequence < HighlightOption->MaxSequence) {\r
260 HighlightPos = HighlightPos->ForwardLink;\r
261 } else {\r
262 HighlightPos = gUserSelectableOptions.ForwardLink;\r
263 }\r
264 break;\r
265 case SCAN_LEFT:\r
266 if (HighlightOption->Sequence > HighlightOption->MinSequence) {\r
267 HighlightPos = HighlightPos->BackLink;\r
268 } else {\r
269 HighlightPos = gUserSelectableOptions.BackLink;\r
270 }\r
271 break;\r
272 default:\r
273 break;\r
274 }\r
275 break;\r
276\r
277 case CHAR_CARRIAGE_RETURN:\r
278 *UserSelection = HighlightOption->OptionType;\r
279 return;\r
280 default:\r
281 if (((KeyValue.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (*gConfirmOptYes | UPPER_LOWER_CASE_OFFSET)) &&\r
282 (PopupType == EfiHiiPopupTypeYesNo || PopupType == EfiHiiPopupTypeYesNoCancel)) {\r
283 *UserSelection = EfiHiiPopupSelectionYes;\r
284 return;\r
285 } else if ((KeyValue.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (*gConfirmOptNo| UPPER_LOWER_CASE_OFFSET) &&\r
286 (PopupType == EfiHiiPopupTypeYesNo || PopupType == EfiHiiPopupTypeYesNoCancel)){\r
287 *UserSelection = EfiHiiPopupSelectionNo;\r
288 return;\r
289 } else if ((KeyValue.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (*gConfirmOptOk | UPPER_LOWER_CASE_OFFSET) &&\r
290 (PopupType == EfiHiiPopupTypeOk || PopupType == EfiHiiPopupTypeOkCancel)){\r
291 *UserSelection = EfiHiiPopupSelectionOk;\r
292 return;\r
293 } else if ((KeyValue.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (*gConfirmOptCancel| UPPER_LOWER_CASE_OFFSET) &&\r
294 (PopupType == EfiHiiPopupTypeOkCancel || PopupType == EfiHiiPopupTypeYesNoCancel)){\r
295 *UserSelection = EfiHiiPopupSelectionCancel;\r
296 return;\r
297 }\r
298 break;\r
299 }\r
300 } while (TRUE);\r
301}\r
302\r
303/**\r
304 Get the offset in the input string when the width reaches to a fixed one.\r
305\r
306 The input string may contain NARROW_CHAR and WIDE_CHAR.\r
307 Notice: the input string doesn't contain line break characters.\r
308\r
309 @param String The input string to be counted.\r
310 @param MaxWidth The max length this function supported.\r
311 @param Offset The max index of the string can be show out. If string's width less than MaxWidth, offset will point to the "\0" of the string.\r
312\r
313**/\r
314VOID\r
315GetStringOffsetWithWidth (\r
316 IN CHAR16 *String,\r
317 IN UINTN MaxWidth,\r
318 OUT UINTN *Offset\r
319 )\r
320{\r
321 UINTN StringWidth;\r
322 UINTN CharWidth;\r
323 UINTN StrOffset;\r
324\r
325 StringWidth = 0;\r
326 CharWidth = 1;\r
327\r
328 for (StrOffset = 0; String[StrOffset] != CHAR_NULL; StrOffset++) {\r
329 switch (String[StrOffset]) {\r
330 case NARROW_CHAR:\r
331 CharWidth = 1;\r
332 break;\r
333 case WIDE_CHAR:\r
334 CharWidth = 2;\r
335 break;\r
336 default:\r
337 StringWidth += CharWidth;\r
338 if (StringWidth >= MaxWidth) {\r
339 *Offset = StrOffset;\r
340 return;\r
341 }\r
342 }\r
343 }\r
344 *Offset = StrOffset;\r
345}\r
346\r
347/**\r
348 Parse the message to check if it contains line break characters.\r
349 For once call, caller can get the string for one line and the width of the string.\r
350 This function call be called recursively to parse the whole InputString.\r
351\r
352 (Notice: current implementation, it only checks \r, \n characters, it deals \r,\n,\n\r same as \r\n.)\r
353\r
354 @param InputString String description for this option.\r
355 @param OutputString Buffer to copy the string into, caller is responsible for freeing the buffer.\r
356 @param OutputStrWidth The width of OutputString.\r
357 @param Index Where in InputString to start the copy process\r
358\r
359 @return Returns the number of CHAR16 characters that were copied into the OutputString buffer, include the '\0' info.\r
360\r
361**/\r
362UINTN\r
363ParseMessageString (\r
364 IN CHAR16 *InputString,\r
365 OUT CHAR16 **OutputString,\r
366 OUT UINTN *OutputStrWidth,\r
367 IN OUT UINTN *Index\r
368 )\r
369{\r
370 UINTN StrOffset;\r
371\r
372 if (InputString == NULL || Index == NULL || OutputString == NULL) {\r
373 return 0;\r
374 }\r
375\r
376 *OutputStrWidth = 0;\r
377\r
378 //\r
379 //Check the string to see if there are line break characters in the string\r
380 //\r
381 for (StrOffset = 0;\r
382 InputString[*Index + StrOffset] != CHAR_CARRIAGE_RETURN && InputString[*Index + StrOffset] != CHAR_LINEFEED && InputString[*Index + StrOffset] != CHAR_NULL;\r
383 StrOffset++\r
384 );\r
385\r
386 //\r
387 // The CHAR_NULL has process last time, this time just return 0 to stand for finishing parsing the InputString.\r
388 //\r
389 if (StrOffset == 0 && (InputString[*Index + StrOffset] == CHAR_NULL)) {\r
390 return 0;\r
391 }\r
392\r
393 //\r
394 // Copy the string to OutputString buffer and calculate the width of OutputString.\r
395 //\r
396 *OutputString = AllocateZeroPool ((StrOffset + 1) * sizeof(CHAR16));\r
397 if (*OutputString == NULL) {\r
398 return 0;\r
399 }\r
400 CopyMem ((*OutputString), &InputString[*Index], StrOffset * sizeof(CHAR16));\r
401 *OutputStrWidth = (GetStringWidth (*OutputString) -2) / 2;\r
402\r
403 //\r
404 // Update the value of Index, can be used for marking where to check the input string for next call.\r
405 //\r
406 if (InputString[*Index + StrOffset] == CHAR_LINEFEED) {\r
407 //\r
408 // Skip the /n or /n/r info.\r
409 //\r
410 if (InputString[*Index + StrOffset + 1] == CHAR_CARRIAGE_RETURN) {\r
411 *Index = (*Index + StrOffset + 2);\r
412 } else {\r
413 *Index = (*Index + StrOffset + 1);\r
414 }\r
415 } else if (InputString[*Index + StrOffset] == CHAR_CARRIAGE_RETURN) {\r
416 //\r
417 // Skip the /r or /r/n info.\r
418 //\r
419 if (InputString[*Index + StrOffset + 1] == CHAR_LINEFEED) {\r
420 *Index = (*Index + StrOffset + 2);\r
421 } else {\r
422 *Index = (*Index + StrOffset + 1);\r
423 }\r
424 } else {\r
425 *Index = (*Index + StrOffset);\r
426 }\r
427\r
428 return StrOffset + 1;\r
429}\r
430\r
431/**\r
432 Calculate the position of the popup.\r
433\r
434 @param PopupType Type of the popup to display.\r
435 @param ScreenForPopup The screen dimensions for the popup.\r
436\r
437**/\r
438VOID\r
439CalculatePopupPosition (\r
440 IN EFI_HII_POPUP_TYPE PopupType,\r
441 OUT EFI_SCREEN_DESCRIPTOR *ScreenForPopup\r
442 )\r
443{\r
444 CHAR16 *OutputString;\r
445 UINTN StringIndex;\r
446 UINTN OutputStrWidth;\r
447 UINTN OptionRowWidth;\r
448 UINTN Columns;\r
449 UINTN Rows;\r
450\r
451 OptionRowWidth = 0;\r
452\r
453 //\r
454 // Calculate the row number which is needed to show the message string and the max width of the string in one row.\r
455 //\r
456 for (StringIndex = 0; ParseMessageString (gMessageString, &OutputString, &OutputStrWidth, &StringIndex) != 0;) {\r
457 gMesStrLineNum ++;\r
458 if (gMaxRowWidth < OutputStrWidth) {\r
459 gMaxRowWidth = OutputStrWidth;\r
460 }\r
461 FreePool (OutputString);\r
462 }\r
463\r
464 //\r
465 // Calculate the row width for the selectable options.(OptionRowWidth = Number * SkipWidth + OptionWidth)\r
466 //\r
467 if (PopupType == EfiHiiPopupTypeOk) {\r
468 OptionRowWidth = USER_SELECTABLE_OPTION_SKIP_WIDTH *2 + USER_SELECTABLE_OPTION_OK_WIDTH;\r
469 } else if (PopupType == EfiHiiPopupTypeOkCancel) {\r
470 OptionRowWidth = USER_SELECTABLE_OPTION_SKIP_WIDTH *3 + USER_SELECTABLE_OPTION_OK_CAL_WIDTH;\r
471 } else if (PopupType == EfiHiiPopupTypeYesNo) {\r
472 OptionRowWidth = USER_SELECTABLE_OPTION_SKIP_WIDTH *3 + USER_SELECTABLE_OPTION_YES_NO_WIDTH;\r
473 } else if (PopupType == EfiHiiPopupTypeYesNoCancel) {\r
474 OptionRowWidth = USER_SELECTABLE_OPTION_SKIP_WIDTH *4 + USER_SELECTABLE_OPTION_YES_NO_CAL_WIDTH;\r
475 }\r
476 if (OptionRowWidth > gMaxRowWidth) {\r
477 gMaxRowWidth = OptionRowWidth;\r
478 }\r
479\r
480 //\r
481 // Avialble row width for message string = screen width - left popup border width - right popup border width.\r
482 // Avialble line number for message string = screen height - 1 - popup header height - popup footer height.\r
483 // (Notice: screen height - 1 because in current UI page, the bottom row of srceen is usded to show Status Bar,not for form itself.\r
484 // So we don't use the bottom row for popup either. If macro STATUS_BAR_HEIGHT changed, we also need to update the height here.)\r
485 //\r
486 // Select the smaller one between actual dimension of message string and the avialble dimension for message string.\r
487 //\r
488 gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Columns, &Rows);\r
489 gMaxRowWidth = MIN (gMaxRowWidth, Columns - 2 * POPUP_BORDER);\r
490 gMesStrLineNum = MIN (gMesStrLineNum, Rows -1 - POPUP_FOOTER_HEIGHT - POPUP_HEADER_HEIGHT);\r
491\r
492 //\r
493 // Calculate the start column, end column, top row and bottom row for the popup.\r
494 //\r
495 ScreenForPopup->LeftColumn = (Columns -2 * POPUP_BORDER - gMaxRowWidth) / 2;\r
496 ScreenForPopup->RightColumn = ScreenForPopup->LeftColumn + gMaxRowWidth + 2 * POPUP_BORDER - 1;\r
497 ScreenForPopup->TopRow = (Rows - 1 - POPUP_FOOTER_HEIGHT - POPUP_HEADER_HEIGHT - gMesStrLineNum) / 2;\r
498 ScreenForPopup->BottomRow = ScreenForPopup->TopRow + gMesStrLineNum + POPUP_FOOTER_HEIGHT + POPUP_HEADER_HEIGHT - 1;\r
499}\r
500\r
501/**\r
502 Draw the Message box.\r
503 +-------------------------------------------+\r
504 | ERROR/WARNING/INFO |\r
505 |-------------------------------------------|\r
506 | popup messages |\r
507 | |\r
508 | user selectable options |\r
509 +-------------------------------------------+\r
510\r
511 @param PopupStyle Popup style to use.\r
512\r
513**/\r
514EFI_STATUS\r
515DrawMessageBox (\r
516 IN EFI_HII_POPUP_STYLE PopupStyle\r
517 )\r
518{\r
519 UINTN Index;\r
520 UINTN Length;\r
521 UINTN EndCol;\r
522 UINTN TopRow;\r
523 UINTN StartCol;\r
524 UINTN BottomRow;\r
525 CHAR16 Character;\r
526 UINTN DisplayRow;\r
527 UINTN StringIndex;\r
528 CHAR16 *TempString;\r
529 CHAR16 *OutputString;\r
530 UINTN ColDimension;\r
531 UINTN OutputStrWidth;\r
532 UINTN DrawMesStrRowNum;\r
533\r
534 EndCol = gPopupDimensions.RightColumn;\r
535 TopRow = gPopupDimensions.TopRow;\r
536 StartCol = gPopupDimensions.LeftColumn;\r
537 BottomRow = gPopupDimensions.BottomRow;\r
538 ColDimension = EndCol - StartCol + 1;\r
539 DrawMesStrRowNum = 0;\r
540\r
541 //\r
542 // 1. Draw the top of the message box.\r
543 //\r
544 Character = BOXDRAW_DOWN_RIGHT;\r
545 PrintCharAt (StartCol, TopRow, Character);\r
546 Character = BOXDRAW_HORIZONTAL;\r
547 for (Index = StartCol; Index + 1 < EndCol; Index++) {\r
548 PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
549 }\r
550 Character = BOXDRAW_DOWN_LEFT;\r
551 PrintCharAt ((UINTN)-1, (UINTN)-1, Character);\r
552\r
553 //\r
554 // 2. Draw the prompt string for different popup styles.\r
555 //\r
556 Character = BOXDRAW_VERTICAL;\r
557 DisplayRow = TopRow + POPUP_BORDER;\r
558 ClearLines (StartCol, EndCol, DisplayRow, DisplayRow, GetPopupColor ());\r
559 PrintCharAt (StartCol, DisplayRow, Character);\r
560 PrintCharAt (EndCol, DisplayRow, Character);\r
561 if (PopupStyle == EfiHiiPopupStyleError) {\r
562 PrintStringAt ((ColDimension - (GetStringWidth (gErrorPopup) - 2) / 2) / 2 + StartCol, DisplayRow, gErrorPopup);\r
563 } else if (PopupStyle == EfiHiiPopupStyleWarning) {\r
564 PrintStringAt ((ColDimension - (GetStringWidth (gWarningPopup) - 2) / 2) / 2 + StartCol, DisplayRow, gWarningPopup);\r
565 } else {\r
566 PrintStringAt ((ColDimension - (GetStringWidth (gInfoPopup) - 2) / 2) / 2 + StartCol, DisplayRow, gInfoPopup);\r
567 }\r
568\r
569 //\r
570 // 3. Draw the horizontal line below the prompt string for different popup styles.\r
571 //\r
572 DisplayRow = TopRow + POPUP_BORDER + POPUP_STYLE_STRING_HEIGHT;\r
573 ClearLines (StartCol, EndCol, DisplayRow, DisplayRow, GetPopupColor ());\r
574 Character = BOXDRAW_HORIZONTAL;\r
575 for (Index = StartCol + 1; Index < EndCol; Index++) {\r
576 PrintCharAt (Index, DisplayRow, Character);\r
577 }\r
578 Character = BOXDRAW_VERTICAL;\r
579 PrintCharAt (StartCol, DisplayRow, Character);\r
580 PrintCharAt (EndCol, DisplayRow, Character);\r
581\r
582 //\r
583 // 4. Draw the mesage string.\r
584 //\r
585 DisplayRow = TopRow + POPUP_HEADER_HEIGHT;\r
586 for (Index = DisplayRow ,StringIndex = 0; ParseMessageString (gMessageString, &OutputString, &OutputStrWidth, &StringIndex) != 0 && DrawMesStrRowNum < gMesStrLineNum;) {\r
587 ClearLines (StartCol, EndCol, Index, Index, GetPopupColor ());\r
588 PrintCharAt (StartCol, Index, Character);\r
589 PrintCharAt (EndCol, Index, Character);\r
590 if (OutputStrWidth > gMaxRowWidth) {\r
591 //\r
592 //OutputStrWidth > MaxMesStrWidth, cut off the string and print print ... instead.\r
593 //\r
594 GetStringOffsetWithWidth (OutputString, gMaxRowWidth, &Length);\r
595 TempString = AllocateZeroPool ((Length + 1) * sizeof (CHAR16));\r
596 if (TempString == NULL) {\r
597 FreePool (OutputString);\r
598 return EFI_OUT_OF_RESOURCES;\r
599 }\r
600 StrnCpyS (TempString, Length + 1, OutputString, Length - 3);\r
601 StrCatS (TempString, Length + 1, L"...");\r
602 PrintStringAt ((ColDimension - gMaxRowWidth) / 2 + StartCol, Index, TempString);\r
603 FreePool (TempString);\r
604 } else {\r
605 PrintStringAt ((ColDimension - OutputStrWidth) / 2 + StartCol, Index, OutputString);\r
606 }\r
607 Index ++;\r
608 DrawMesStrRowNum ++;\r
609 FreePool (OutputString);\r
610 }\r
611\r
612 //\r
613 // 5. Draw an empty line after message string.\r
614 //\r
615 ClearLines (StartCol, EndCol, Index, Index, GetPopupColor ());\r
616 PrintCharAt (StartCol, Index, Character);\r
617 PrintCharAt (EndCol, Index, Character);\r
618 //\r
619 // Check whether the actual string row number beyond the MesStrRowNum, if yes, print the ...... in the row.\r
620 //\r
621 if (OutputStrWidth > 0 && DrawMesStrRowNum >= gMesStrLineNum) {\r
622 PrintStringAt ((ColDimension - StrLen (L"......")) / 2 + StartCol, Index, L"......");\r
623 }\r
624\r
625 //\r
626 // 6. Draw an empty line which is used to show user selectable options, will draw concrete option strings in function GetUserSelection().\r
627 //\r
628 Character = BOXDRAW_VERTICAL;\r
629 DisplayRow = BottomRow - POPUP_BORDER;\r
630 ClearLines (StartCol, EndCol, DisplayRow, DisplayRow, GetPopupColor ());\r
631 PrintCharAt (StartCol, DisplayRow, Character);\r
632 PrintCharAt (EndCol, DisplayRow, Character);\r
633\r
634 //\r
635 // 7. Draw the bottom of the message box.\r
636 //\r
637 Character = BOXDRAW_UP_RIGHT;\r
638 PrintCharAt (StartCol, BottomRow, Character);\r
639 Character = BOXDRAW_HORIZONTAL;\r
640 for (Index = StartCol; Index + 1 < EndCol; Index++) {\r
641 PrintCharAt ((UINTN)-1, (UINTN) -1, Character);\r
642 }\r
643 Character = BOXDRAW_UP_LEFT;\r
644 PrintCharAt ((UINTN)-1, (UINTN) -1, Character);\r
645\r
646 return EFI_SUCCESS;\r
647}\r
648\r
649/**\r
650 Displays a popup window.\r
651\r
652 @param This A pointer to the EFI_HII_POPUP_PROTOCOL instance.\r
653 @param PopupStyle Popup style to use.\r
654 @param PopupType Type of the popup to display.\r
655 @param HiiHandle HII handle of the string pack containing Message\r
656 @param Message A message to display in the popup box.\r
657 @param UserSelection User selection.\r
658\r
659 @retval EFI_SUCCESS The popup box was successfully displayed.\r
660 @retval EFI_INVALID_PARAMETER HiiHandle and Message do not define a valid HII string.\r
661 @retval EFI_INVALID_PARAMETER PopupType is not one of the values defined by this specification.\r
662 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to display the popup box.\r
663\r
664**/\r
665EFI_STATUS\r
666EFIAPI\r
667CreatePopup (\r
668 IN EFI_HII_POPUP_PROTOCOL *This,\r
669 IN EFI_HII_POPUP_STYLE PopupStyle,\r
670 IN EFI_HII_POPUP_TYPE PopupType,\r
671 IN EFI_HII_HANDLE HiiHandle,\r
672 IN EFI_STRING_ID Message,\r
673 OUT EFI_HII_POPUP_SELECTION *UserSelection OPTIONAL\r
674 )\r
675{\r
676 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;\r
677 EFI_SIMPLE_TEXT_OUTPUT_MODE SavedConsoleMode;\r
678 EFI_STATUS Status;\r
679\r
680 if ((PopupType < EfiHiiPopupTypeOk) || (PopupType > EfiHiiPopupTypeYesNoCancel)) {\r
681 return EFI_INVALID_PARAMETER;\r
682 }\r
683\r
684 if((HiiHandle == NULL) || (Message == 0)) {\r
685 return EFI_INVALID_PARAMETER;\r
686 }\r
687\r
688 gMessageString = HiiGetString (HiiHandle, Message, NULL);\r
2f808acc 689 if(gMessageString == NULL) {\r
06aad9a2
DB
690 return EFI_INVALID_PARAMETER;\r
691 }\r
692\r
693 ConOut = gST->ConOut;\r
694 gMaxRowWidth = 0;\r
695 gMesStrLineNum = 0;\r
696\r
697 CopyMem (&SavedConsoleMode, ConOut->Mode, sizeof (SavedConsoleMode));\r
698 ConOut->EnableCursor (ConOut, FALSE);\r
699 ConOut->SetAttribute (ConOut, GetPopupColor ());\r
700\r
701 CalculatePopupPosition (PopupType, &gPopupDimensions);\r
702\r
703 Status = DrawMessageBox (PopupStyle);\r
704 if (EFI_ERROR (Status)) {\r
705 goto Done;\r
706 }\r
707\r
708 //\r
709 // Add user selectable options to option list: gUserSelectableOptions\r
710 //\r
711 Status = AddUserSelectableOptions (PopupType);\r
712 if (EFI_ERROR (Status)) {\r
713 goto Done;\r
714 }\r
715\r
716 GetUserSelection (PopupType, UserSelection);\r
717\r
718Done:\r
719 //\r
720 // Restore Conout attributes and free the resources allocate before.\r
721 //\r
722 ConOut->EnableCursor (ConOut, SavedConsoleMode.CursorVisible);\r
723 ConOut->SetCursorPosition (ConOut, SavedConsoleMode.CursorColumn, SavedConsoleMode.CursorRow);\r
724 ConOut->SetAttribute (ConOut, SavedConsoleMode.Attribute);\r
725 FreeSelectableOptions (&gUserSelectableOptions);\r
726 FreePool (gMessageString);\r
727\r
728 return Status;\r
729}\r
730\r