- Added support for NTLDR style freeloader GUI. To enable, edit freeldr.ini and add:
[reactos.git] / reactos / boot / freeldr / freeldr / ui / ui.c
1 /*
2 * FreeLoader
3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <freeldr.h>
21
22 #define NDEBUG
23 #include <debug.h>
24
25
26 ULONG UiScreenWidth = 80; // Screen Width
27 ULONG UiScreenHeight = 25; // Screen Height
28
29 UCHAR UiStatusBarFgColor = COLOR_BLACK; // Status bar foreground color
30 UCHAR UiStatusBarBgColor = COLOR_CYAN; // Status bar background color
31 UCHAR UiBackdropFgColor = COLOR_WHITE; // Backdrop foreground color
32 UCHAR UiBackdropBgColor = COLOR_BLUE; // Backdrop background color
33 UCHAR UiBackdropFillStyle = MEDIUM_FILL; // Backdrop fill style
34 UCHAR UiTitleBoxFgColor = COLOR_WHITE; // Title box foreground color
35 UCHAR UiTitleBoxBgColor = COLOR_RED; // Title box background color
36 UCHAR UiMessageBoxFgColor = COLOR_WHITE; // Message box foreground color
37 UCHAR UiMessageBoxBgColor = COLOR_BLUE; // Message box background color
38 UCHAR UiMenuFgColor = COLOR_WHITE; // Menu foreground color
39 UCHAR UiMenuBgColor = COLOR_BLUE; // Menu background color
40 UCHAR UiTextColor = COLOR_YELLOW; // Normal text color
41 UCHAR UiSelectedTextColor = COLOR_BLACK; // Selected text color
42 UCHAR UiSelectedTextBgColor = COLOR_GRAY; // Selected text background color
43 UCHAR UiEditBoxTextColor = COLOR_WHITE; // Edit box text color
44 UCHAR UiEditBoxBgColor = COLOR_BLACK; // Edit box text background color
45
46 CHAR UiTitleBoxTitleText[260] = "Boot Menu"; // Title box's title text
47
48 BOOL UserInterfaceUp = FALSE; // Tells us if the user interface is displayed
49
50 VIDEODISPLAYMODE UiDisplayMode = VideoTextMode; // Tells us if we are in text or graphics mode
51
52 BOOL UiUseSpecialEffects = FALSE; // Tells us if we should use fade effects
53 BOOL UiDrawTime = TRUE; // Tells us if we should draw the time
54 BOOL UiMinimal = FALSE; // Tells us if we should use a minimal console-like UI
55 BOOL UiCenterMenu = TRUE; // Tells us if we should use a centered or left-aligned menu
56 BOOL UiMenuBox = TRUE; // Tells us if we shuld draw a box around the menu
57 CHAR UiTimeText[260] = "[Time Remaining: ] ";
58
59 const CHAR UiMonthNames[12][15] = { "January ", "February ", "March ", "April ", "May ", "June ", "July ", "August ", "September ", "October ", "November ", "December " };
60
61
62 BOOL UiInitialize(BOOLEAN ShowGui)
63 {
64 ULONG SectionId;
65 CHAR DisplayModeText[260];
66 CHAR SettingText[260];
67 ULONG Depth;
68
69 if (!ShowGui) {
70 if (!TuiInitialize())
71 {
72 MachVideoSetDisplayMode(NULL, FALSE);
73 return FALSE;
74 }
75 UserInterfaceUp = FALSE;
76 return TRUE;
77 }
78
79 DbgPrint((DPRINT_UI, "Initializing User Interface.\n"));
80
81 DbgPrint((DPRINT_UI, "Reading in UI settings from [Display] section.\n"));
82
83 DisplayModeText[0] = '\0';
84 if (IniOpenSection("Display", &SectionId))
85 {
86 if (! IniReadSettingByName(SectionId, "DisplayMode", DisplayModeText, 260))
87 {
88 DisplayModeText[0] = '\0';
89 }
90
91 if (IniReadSettingByName(SectionId, "TitleText", SettingText, 260))
92 {
93 strcpy(UiTitleBoxTitleText, SettingText);
94 }
95 if (IniReadSettingByName(SectionId, "TimeText", SettingText, 260))
96 {
97 strcpy(UiTimeText, SettingText);
98 }
99 if (IniReadSettingByName(SectionId, "StatusBarColor", SettingText, 260))
100 {
101 UiStatusBarBgColor = UiTextToColor(SettingText);
102 }
103 if (IniReadSettingByName(SectionId, "StatusBarTextColor", SettingText, 260))
104 {
105 UiStatusBarFgColor = UiTextToColor(SettingText);
106 }
107 if (IniReadSettingByName(SectionId, "BackdropTextColor", SettingText, 260))
108 {
109 UiBackdropFgColor = UiTextToColor(SettingText);
110 }
111 if (IniReadSettingByName(SectionId, "BackdropColor", SettingText, 260))
112 {
113 UiBackdropBgColor = UiTextToColor(SettingText);
114 }
115 if (IniReadSettingByName(SectionId, "BackdropFillStyle", SettingText, 260))
116 {
117 UiBackdropFillStyle = UiTextToFillStyle(SettingText);
118 }
119 if (IniReadSettingByName(SectionId, "TitleBoxTextColor", SettingText, 260))
120 {
121 UiTitleBoxFgColor = UiTextToColor(SettingText);
122 }
123 if (IniReadSettingByName(SectionId, "TitleBoxColor", SettingText, 260))
124 {
125 UiTitleBoxBgColor = UiTextToColor(SettingText);
126 }
127 if (IniReadSettingByName(SectionId, "MessageBoxTextColor", SettingText, 260))
128 {
129 UiMessageBoxFgColor = UiTextToColor(SettingText);
130 }
131 if (IniReadSettingByName(SectionId, "MessageBoxColor", SettingText, 260))
132 {
133 UiMessageBoxBgColor = UiTextToColor(SettingText);
134 }
135 if (IniReadSettingByName(SectionId, "MenuTextColor", SettingText, 260))
136 {
137 UiMenuFgColor = UiTextToColor(SettingText);
138 }
139 if (IniReadSettingByName(SectionId, "MenuColor", SettingText, 260))
140 {
141 UiMenuBgColor = UiTextToColor(SettingText);
142 }
143 if (IniReadSettingByName(SectionId, "TextColor", SettingText, 260))
144 {
145 UiTextColor = UiTextToColor(SettingText);
146 }
147 if (IniReadSettingByName(SectionId, "SelectedTextColor", SettingText, 260))
148 {
149 UiSelectedTextColor = UiTextToColor(SettingText);
150 }
151 if (IniReadSettingByName(SectionId, "SelectedColor", SettingText, 260))
152 {
153 UiSelectedTextBgColor = UiTextToColor(SettingText);
154 }
155 if (IniReadSettingByName(SectionId, "EditBoxTextColor", SettingText, 260))
156 {
157 UiEditBoxTextColor = UiTextToColor(SettingText);
158 }
159 if (IniReadSettingByName(SectionId, "EditBoxColor", SettingText, 260))
160 {
161 UiEditBoxBgColor = UiTextToColor(SettingText);
162 }
163 if (IniReadSettingByName(SectionId, "SpecialEffects", SettingText, 260))
164 {
165 if (_stricmp(SettingText, "Yes") == 0 && strlen(SettingText) == 3)
166 {
167 UiUseSpecialEffects = TRUE;
168 }
169 else
170 {
171 UiUseSpecialEffects = FALSE;
172 }
173 }
174 if (IniReadSettingByName(SectionId, "ShowTime", SettingText, 260))
175 {
176 if (_stricmp(SettingText, "Yes") == 0 && strlen(SettingText) == 3)
177 {
178 UiDrawTime = TRUE;
179 }
180 else
181 {
182 UiDrawTime = FALSE;
183 }
184 }
185 if (IniReadSettingByName(SectionId, "MinimalUI", SettingText, 260))
186 {
187 if (_stricmp(SettingText, "Yes") == 0 && strlen(SettingText) == 3)
188 {
189 UiMinimal = TRUE;
190 }
191 else
192 {
193 UiMinimal = FALSE;
194 }
195 }
196 if (IniReadSettingByName(SectionId, "MenuBox", SettingText, 260))
197 {
198 if (_stricmp(SettingText, "Yes") == 0 && strlen(SettingText) == 3)
199 {
200 UiMenuBox = TRUE;
201 }
202 else
203 {
204 UiMenuBox = FALSE;
205 }
206 }
207 if (IniReadSettingByName(SectionId, "CenterMenu", SettingText, 260))
208 {
209 if (_stricmp(SettingText, "Yes") == 0 && strlen(SettingText) == 3)
210 {
211 UiCenterMenu = TRUE;
212 }
213 else
214 {
215 UiCenterMenu = FALSE;
216 }
217 }
218 }
219
220 UiDisplayMode = MachVideoSetDisplayMode(DisplayModeText, TRUE);
221 MachVideoGetDisplaySize(&UiScreenWidth, &UiScreenHeight, &Depth);
222
223
224 if (VideoTextMode == UiDisplayMode)
225 {
226 if (!TuiInitialize())
227 {
228 MachVideoSetDisplayMode(NULL, FALSE);
229 return FALSE;
230 }
231 }
232 else
233 {
234 UNIMPLEMENTED();
235 //if (!GuiInitialize())
236 //{
237 // MachSetDisplayMode(NULL, FALSE);
238 // return FALSE;
239 //}
240 }
241
242 // Draw the backdrop and fade it in if special effects are enabled
243 UiFadeInBackdrop();
244
245 UserInterfaceUp = TRUE;
246
247 DbgPrint((DPRINT_UI, "UiInitialize() returning TRUE.\n"));
248 return TRUE;
249 }
250
251 BOOL SetupUiInitialize(VOID)
252 {
253
254 CHAR DisplayModeText[260];
255 ULONG Depth;
256
257
258 DisplayModeText[0] = '\0';
259
260
261 UiDisplayMode = MachVideoSetDisplayMode(DisplayModeText, TRUE);
262 MachVideoGetDisplaySize(&UiScreenWidth, &UiScreenHeight, &Depth);
263
264 TuiInitialize();
265
266 // Draw the backdrop and fade it in if special effects are enabled
267 TuiFillArea(0,
268 0,
269 UiScreenWidth - 1,
270 UiScreenHeight - 2,
271 0,
272 ATTR(UiBackdropFgColor, UiBackdropBgColor));
273
274 UiStatusBarBgColor = 7;
275 UserInterfaceUp = TRUE;
276
277 TuiDrawText(4, 1, "ReactOS " KERNEL_VERSION_STR " Setup", ATTR(COLOR_GRAY, UiBackdropBgColor));
278 TuiDrawText(3, 2, "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD", ATTR(COLOR_GRAY, UiBackdropBgColor));
279
280 DbgPrint((DPRINT_UI, "UiInitialize() returning TRUE.\n"));
281
282 return TRUE;
283 }
284
285 VOID UiUnInitialize(PCSTR BootText)
286 {
287 UiDrawBackdrop();
288 UiDrawStatusText("Booting...");
289 UiInfoBox(BootText);
290
291 if (VideoTextMode == UiDisplayMode)
292 {
293 TuiUnInitialize();
294 }
295 else
296 {
297 UNIMPLEMENTED();
298 //GuiUnInitialize();
299 }
300 }
301
302 VOID UiDrawBackdrop(VOID)
303 {
304 if (!UserInterfaceUp) return;
305
306 if (VideoTextMode == UiDisplayMode)
307 {
308 TuiDrawBackdrop();
309 }
310 else
311 {
312 UNIMPLEMENTED();
313 //GuiDrawBackdrop();
314 }
315 }
316
317 VOID UiFillArea(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, CHAR FillChar, UCHAR Attr /* Color Attributes */)
318 {
319 if (VideoTextMode == UiDisplayMode)
320 {
321 TuiFillArea(Left, Top, Right, Bottom, FillChar, Attr);
322 }
323 else
324 {
325 UNIMPLEMENTED();
326 //GuiFillArea(Left, Top, Right, Bottom, FillChar, Attr);
327 }
328 }
329
330 VOID UiDrawShadow(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom)
331 {
332 if (VideoTextMode == UiDisplayMode)
333 {
334 TuiDrawShadow(Left, Top, Right, Bottom);
335 }
336 else
337 {
338 UNIMPLEMENTED();
339 //GuiDrawShadow(Left, Top, Right, Bottom);
340 }
341 }
342
343 VOID UiDrawBox(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOL Fill, BOOL Shadow, UCHAR Attr)
344 {
345 if (VideoTextMode == UiDisplayMode)
346 {
347 TuiDrawBox(Left, Top, Right, Bottom, VertStyle, HorzStyle, Fill, Shadow, Attr);
348 }
349 else
350 {
351 UNIMPLEMENTED();
352 //GuiDrawBox(Left, Top, Right, Bottom, VertStyle, HorzStyle, Fill, Shadow, Attr);
353 }
354 }
355
356 VOID UiDrawText(ULONG X, ULONG Y, PCSTR Text, UCHAR Attr)
357 {
358 if (VideoTextMode == UiDisplayMode)
359 {
360 TuiDrawText(X, Y, Text, Attr);
361 }
362 else
363 {
364 UNIMPLEMENTED();
365 //GuiDrawText(X, Y, Text, Attr);
366 }
367 }
368
369 VOID UiDrawCenteredText(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, PCSTR TextString, UCHAR Attr)
370 {
371 if (VideoTextMode == UiDisplayMode)
372 {
373 TuiDrawCenteredText(Left, Top, Right, Bottom, TextString, Attr);
374 }
375 else
376 {
377 UNIMPLEMENTED();
378 //GuiDrawCenteredText(Left, Top, Right, Bottom, TextString, Attr);
379 }
380 }
381
382 VOID UiDrawStatusText(PCSTR StatusText)
383 {
384 if (!UserInterfaceUp) return;
385
386 if (VideoTextMode == UiDisplayMode)
387 {
388 TuiDrawStatusText(StatusText);
389 }
390 else
391 {
392 UNIMPLEMENTED();
393 //GuiDrawStatusText(StatusText);
394 }
395 }
396
397 VOID UiUpdateDateTime(VOID)
398 {
399 if (VideoTextMode == UiDisplayMode)
400 {
401 TuiUpdateDateTime();
402 }
403 else
404 {
405 UNIMPLEMENTED();
406 //GuiUpdateDateTime();
407 }
408 }
409
410 VOID UiInfoBox(PCSTR MessageText)
411 {
412 ULONG TextLength;
413 ULONG BoxWidth;
414 ULONG BoxHeight;
415 ULONG LineBreakCount;
416 ULONG Index;
417 ULONG LastIndex;
418 ULONG Left;
419 ULONG Top;
420 ULONG Right;
421 ULONG Bottom;
422
423 TextLength = strlen(MessageText);
424
425 // Count the new lines and the box width
426 LineBreakCount = 0;
427 BoxWidth = 0;
428 LastIndex = 0;
429 for (Index=0; Index<TextLength; Index++)
430 {
431 if (MessageText[Index] == '\n')
432 {
433 LastIndex = Index;
434 LineBreakCount++;
435 }
436 else
437 {
438 if ((Index - LastIndex) > BoxWidth)
439 {
440 BoxWidth = (Index - LastIndex);
441 }
442 }
443 }
444
445 // Calc the box width & height
446 BoxWidth += 6;
447 BoxHeight = LineBreakCount + 4;
448
449 // Calc the box coordinates
450 Left = (UiScreenWidth / 2) - (BoxWidth / 2);
451 Top =(UiScreenHeight / 2) - (BoxHeight / 2);
452 Right = (UiScreenWidth / 2) + (BoxWidth / 2);
453 Bottom = (UiScreenHeight / 2) + (BoxHeight / 2);
454
455 // Draw the box
456 UiDrawBox(Left,
457 Top,
458 Right,
459 Bottom,
460 VERT,
461 HORZ,
462 TRUE,
463 TRUE,
464 ATTR(UiMenuFgColor, UiMenuBgColor)
465 );
466
467 // Draw the text
468 UiDrawCenteredText(Left, Top, Right, Bottom, MessageText, ATTR(UiTextColor, UiMenuBgColor));
469 }
470
471 VOID UiMessageBox(PCSTR MessageText)
472 {
473 // We have not yet displayed the user interface
474 // We are probably still reading the .ini file
475 // and have encountered an error. Just use printf()
476 // and return.
477 if (!UserInterfaceUp)
478 {
479 printf("%s\n", MessageText);
480 printf("Press any key\n");
481 MachConsGetCh();
482 return;
483 }
484
485 if (VideoTextMode == UiDisplayMode)
486 {
487 TuiMessageBox(MessageText);
488 }
489 else
490 {
491 UNIMPLEMENTED();
492 //GuiMessageBox(MessageText);
493 }
494 }
495
496 VOID UiMessageBoxCritical(PCSTR MessageText)
497 {
498 // We have not yet displayed the user interface
499 // We are probably still reading the .ini file
500 // and have encountered an error. Just use printf()
501 // and return.
502 if (!UserInterfaceUp)
503 {
504 printf("%s\n", MessageText);
505 printf("Press any key\n");
506 MachConsGetCh();
507 return;
508 }
509
510 if (VideoTextMode == UiDisplayMode)
511 {
512 TuiMessageBoxCritical(MessageText);
513 }
514 else
515 {
516 UNIMPLEMENTED();
517 //GuiMessageBoxCritical(MessageText);
518 }
519 }
520
521 UCHAR UiTextToColor(PCSTR ColorText)
522 {
523 if (VideoTextMode == UiDisplayMode)
524 {
525 return TuiTextToColor(ColorText);
526 }
527 else
528 {
529 UNIMPLEMENTED();
530 return 0;
531 //return GuiTextToColor(ColorText);
532 }
533 }
534
535 UCHAR UiTextToFillStyle(PCSTR FillStyleText)
536 {
537 if (VideoTextMode == UiDisplayMode)
538 {
539 return TuiTextToFillStyle(FillStyleText);
540 }
541 else
542 {
543 UNIMPLEMENTED();
544 return 0;
545 //return GuiTextToFillStyle(FillStyleText);
546 }
547 }
548
549 VOID UiDrawProgressBarCenter(ULONG Position, ULONG Range, PCHAR ProgressText)
550 {
551 if (!UserInterfaceUp) return;
552
553 if (VideoTextMode == UiDisplayMode)
554 {
555 TuiDrawProgressBarCenter(Position, Range, ProgressText);
556 }
557 else
558 {
559 UNIMPLEMENTED();
560 //GuiDrawProgressBarCenter(Position, Range, ProgressText);
561 }
562 }
563
564 VOID UiDrawProgressBar(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, ULONG Position, ULONG Range, PCHAR ProgressText)
565 {
566 if (VideoTextMode == UiDisplayMode)
567 {
568 TuiDrawProgressBar(Left, Top, Right, Bottom, Position, Range, ProgressText);
569 }
570 else
571 {
572 UNIMPLEMENTED();
573 //GuiDrawProgressBar(Left, Top, Right, Bottom, Position, Range, ProgressText);
574 }
575 }
576
577 VOID UiShowMessageBoxesInSection(PCSTR SectionName)
578 {
579 ULONG Idx;
580 CHAR SettingName[80];
581 CHAR SettingValue[80];
582 PCHAR MessageBoxText;
583 ULONG MessageBoxTextSize;
584 ULONG SectionId;
585
586 if (!IniOpenSection(SectionName, &SectionId))
587 {
588 sprintf(SettingName, "Section %s not found in freeldr.ini.\n", SectionName);
589 UiMessageBox(SettingName);
590 return;
591 }
592
593 //
594 // Find all the message box settings and run them
595 //
596 for (Idx=0; Idx<IniGetNumSectionItems(SectionId); Idx++)
597 {
598 IniReadSettingByNumber(SectionId, Idx, SettingName, 79, SettingValue, 79);
599
600 if (_stricmp(SettingName, "MessageBox") == 0)
601 {
602 // Get the real length of the MessageBox text
603 MessageBoxTextSize = IniGetSectionSettingValueSize(SectionId, Idx);
604
605 //if (MessageBoxTextSize > 0)
606 {
607 // Allocate enough memory to hold the text
608 MessageBoxText = MmAllocateMemory(MessageBoxTextSize);
609
610 if (MessageBoxText)
611 {
612 // Get the MessageBox text
613 IniReadSettingByNumber(SectionId, Idx, SettingName, 80, MessageBoxText, MessageBoxTextSize);
614
615 // Fix it up
616 UiEscapeString(MessageBoxText);
617
618 // Display it
619 UiMessageBox(MessageBoxText);
620
621 // Free the memory
622 MmFreeMemory(MessageBoxText);
623 }
624 }
625 }
626 }
627 }
628
629 VOID UiEscapeString(PCHAR String)
630 {
631 ULONG Idx;
632
633 for (Idx=0; Idx<strlen(String); Idx++)
634 {
635 // Escape the new line characters
636 if (String[Idx] == '\\' && String[Idx+1] == 'n')
637 {
638 // Escape the character
639 String[Idx] = '\n';
640
641 // Move the rest of the string up
642 strcpy(&String[Idx+1], &String[Idx+2]);
643 }
644 }
645 }
646
647 VOID UiTruncateStringEllipsis(PCHAR StringText, ULONG MaxChars)
648 {
649 if (strlen(StringText) > MaxChars)
650 {
651 strcpy(&StringText[MaxChars - 3], "...");
652 }
653 }
654
655 BOOL UiDisplayMenu(PCSTR MenuItemList[], ULONG MenuItemCount, ULONG DefaultMenuItem, LONG MenuTimeOut, ULONG* SelectedMenuItem, BOOL CanEscape, UiMenuKeyPressFilterCallback KeyPressFilter)
656 {
657 if (VideoTextMode == UiDisplayMode)
658 {
659 return TuiDisplayMenu(MenuItemList, MenuItemCount, DefaultMenuItem, MenuTimeOut, SelectedMenuItem, CanEscape, KeyPressFilter);
660 }
661 else
662 {
663 UNIMPLEMENTED();
664 return FALSE;
665 //return GuiDisplayMenu(MenuItemList, MenuItemCount, DefaultMenuItem, MenuTimeOut, SelectedMenuItem, CanEscape, KeyPressFilter);
666 }
667 }
668
669 VOID UiFadeInBackdrop(VOID)
670 {
671 if (VideoTextMode == UiDisplayMode)
672 {
673 TuiFadeInBackdrop();
674 }
675 else
676 {
677 UNIMPLEMENTED();
678 //GuiFadeInBackdrop();
679 }
680 }
681
682 VOID UiFadeOut(VOID)
683 {
684 if (VideoTextMode == UiDisplayMode)
685 {
686 TuiFadeOut();
687 }
688 else
689 {
690 UNIMPLEMENTED();
691 //GuiFadeInOut();
692 }
693 }
694
695 BOOL UiEditBox(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length)
696 {
697 if (VideoTextMode == UiDisplayMode)
698 {
699 return TuiEditBox(MessageText, EditTextBuffer, Length);
700 }
701 else
702 {
703 UNIMPLEMENTED();
704 return FALSE;
705 //return GuiEditBox(MessageText, EditTextBuffer, Length);
706 }
707 }