Spelling fixes. Thanks to Royce for pointing them out.
[reactos.git] / reactos / boot / freeldr / freeldr / ui / tui.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 PVOID TextVideoBuffer = NULL;
23
24 /*
25 * printf() - prints formatted text to stdout
26 * originally from GRUB
27 */
28 int printf(const char *format, ... )
29 {
30 va_list ap;
31 va_start(ap,format);
32 char c, *ptr, str[16];
33
34 while ((c = *(format++)))
35 {
36 if (c != '%')
37 {
38 MachConsPutChar(c);
39 }
40 else
41 {
42 switch (c = *(format++))
43 {
44 case 'd': case 'u': case 'x':
45 if (c == 'x')
46 *_itoa(va_arg(ap, unsigned long), str, 16) = 0;
47 else
48 *_itoa(va_arg(ap, unsigned long), str, 10) = 0;
49
50 ptr = str;
51
52 while (*ptr)
53 {
54 MachConsPutChar(*(ptr++));
55 }
56 break;
57
58 case 'c': MachConsPutChar((va_arg(ap,int))&0xff); break;
59
60 case 's':
61 ptr = va_arg(ap,char *);
62
63 while ((c = *(ptr++)))
64 {
65 MachConsPutChar(c);
66 }
67 break;
68 case '%':
69 MachConsPutChar(c);
70 break;
71 default:
72 printf("\nprintf() invalid format specifier - %%%c\n", c);
73 break;
74 }
75 }
76 }
77
78 va_end(ap);
79
80 return 0;
81 }
82
83 BOOL TuiInitialize(VOID)
84 {
85 MachVideoClearScreen(ATTR(COLOR_WHITE, COLOR_BLACK));
86 MachVideoHideShowTextCursor(FALSE);
87
88 TextVideoBuffer = VideoAllocateOffScreenBuffer();
89 if (TextVideoBuffer == NULL)
90 {
91 return FALSE;
92 }
93
94 return TRUE;
95 }
96
97 VOID TuiUnInitialize(VOID)
98 {
99 if (UiUseSpecialEffects)
100 {
101 TuiFadeOut();
102 }
103 else
104 {
105 MachVideoSetDisplayMode(NULL, FALSE);
106 }
107
108 //VideoClearScreen();
109 MachVideoHideShowTextCursor(TRUE);
110 }
111
112 VOID TuiDrawBackdrop(VOID)
113 {
114 //
115 // Fill in the background (excluding title box & status bar)
116 //
117 TuiFillArea(0,
118 TUI_TITLE_BOX_CHAR_HEIGHT,
119 UiScreenWidth - 1,
120 UiScreenHeight - 2,
121 UiBackdropFillStyle,
122 ATTR(UiBackdropFgColor, UiBackdropBgColor));
123
124 //
125 // Draw the title box
126 //
127 TuiDrawBox(0,
128 0,
129 UiScreenWidth - 1,
130 TUI_TITLE_BOX_CHAR_HEIGHT - 1,
131 D_VERT,
132 D_HORZ,
133 TRUE,
134 FALSE,
135 ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
136
137 //
138 // Draw version text
139 //
140 TuiDrawText(2,
141 1,
142 GetFreeLoaderVersionString(),
143 ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
144
145 //
146 // Draw copyright
147 //
148 TuiDrawText(2,
149 2,
150 BY_AUTHOR,
151 ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
152 TuiDrawText(2,
153 3,
154 AUTHOR_EMAIL,
155 ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
156
157 //
158 // Draw help text
159 //
160 TuiDrawText(UiScreenWidth - 16, 3, /*"F1 for Help"*/"F8 for Options", ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
161
162 //
163 // Draw title text
164 //
165 TuiDrawText( (UiScreenWidth / 2) - (strlen(UiTitleBoxTitleText) / 2),
166 2,
167 UiTitleBoxTitleText,
168 ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
169
170 //
171 // Draw status bar
172 //
173 TuiDrawStatusText("Welcome to FreeLoader!");
174
175 //
176 // Update the date & time
177 //
178 TuiUpdateDateTime();
179
180 VideoCopyOffScreenBufferToVRAM();
181 }
182
183 /*
184 * FillArea()
185 * This function assumes coordinates are zero-based
186 */
187 VOID TuiFillArea(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, CHAR FillChar, UCHAR Attr /* Color Attributes */)
188 {
189 PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer;
190 ULONG i, j;
191
192 // Clip the area to the screen
193 // FIXME: This code seems to have problems... Uncomment and view ;-)
194 /*if ((Left >= UiScreenWidth) || (Top >= UiScreenHeight))
195 {
196 return;
197 }
198 if ((Left + Right) >= UiScreenWidth)
199 {
200 Right = UiScreenWidth - Left;
201 }
202 if ((Top + Bottom) >= UiScreenHeight)
203 {
204 Bottom = UiScreenHeight - Top;
205 }*/
206
207 // Loop through each line and fill it in
208 for (i=Top; i<=Bottom; i++)
209 {
210 // Loop through each character (column) in the line and fill it in
211 for (j=Left; j<=Right; j++)
212 {
213 ScreenMemory[((i*2)*UiScreenWidth)+(j*2)] = (UCHAR)FillChar;
214 ScreenMemory[((i*2)*UiScreenWidth)+(j*2)+1] = Attr;
215 }
216 }
217 }
218
219 /*
220 * DrawShadow()
221 * This function assumes coordinates are zero-based
222 */
223 VOID TuiDrawShadow(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom)
224 {
225 PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer;
226 ULONG Idx;
227
228 // Shade the bottom of the area
229 if (Bottom < (UiScreenHeight - 1))
230 {
231 if (UiScreenHeight < 34)
232 {
233 Idx=Left + 2;
234 }
235 else
236 {
237 Idx=Left + 1;
238 }
239
240 for (; Idx<=Right; Idx++)
241 {
242 ScreenMemory[(((Bottom+1)*2)*UiScreenWidth)+(Idx*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
243 }
244 }
245
246 // Shade the right of the area
247 if (Right < (UiScreenWidth - 1))
248 {
249 for (Idx=Top+1; Idx<=Bottom; Idx++)
250 {
251 ScreenMemory[((Idx*2)*UiScreenWidth)+((Right+1)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
252 }
253 }
254 if (UiScreenHeight < 34)
255 {
256 if ((Right + 1) < (UiScreenWidth - 1))
257 {
258 for (Idx=Top+1; Idx<=Bottom; Idx++)
259 {
260 ScreenMemory[((Idx*2)*UiScreenWidth)+((Right+2)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
261 }
262 }
263 }
264
265 // Shade the bottom right corner
266 if ((Right < (UiScreenWidth - 1)) && (Bottom < (UiScreenHeight - 1)))
267 {
268 ScreenMemory[(((Bottom+1)*2)*UiScreenWidth)+((Right+1)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
269 }
270 if (UiScreenHeight < 34)
271 {
272 if (((Right + 1) < (UiScreenWidth - 1)) && (Bottom < (UiScreenHeight - 1)))
273 {
274 ScreenMemory[(((Bottom+1)*2)*UiScreenWidth)+((Right+2)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
275 }
276 }
277 }
278
279 /*
280 * DrawBox()
281 * This function assumes coordinates are zero-based
282 */
283 VOID TuiDrawBox(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOL Fill, BOOL Shadow, UCHAR Attr)
284 {
285 UCHAR ULCorner, URCorner, LLCorner, LRCorner;
286
287 // Calculate the corner values
288 if (HorzStyle == HORZ)
289 {
290 if (VertStyle == VERT)
291 {
292 ULCorner = UL;
293 URCorner = UR;
294 LLCorner = LL;
295 LRCorner = LR;
296 }
297 else // VertStyle == D_VERT
298 {
299 ULCorner = VD_UL;
300 URCorner = VD_UR;
301 LLCorner = VD_LL;
302 LRCorner = VD_LR;
303 }
304 }
305 else // HorzStyle == D_HORZ
306 {
307 if (VertStyle == VERT)
308 {
309 ULCorner = HD_UL;
310 URCorner = HD_UR;
311 LLCorner = HD_LL;
312 LRCorner = HD_LR;
313 }
314 else // VertStyle == D_VERT
315 {
316 ULCorner = D_UL;
317 URCorner = D_UR;
318 LLCorner = D_LL;
319 LRCorner = D_LR;
320 }
321 }
322
323 // Fill in box background
324 if (Fill)
325 {
326 TuiFillArea(Left, Top, Right, Bottom, ' ', Attr);
327 }
328
329 // Fill in corners
330 TuiFillArea(Left, Top, Left, Top, ULCorner, Attr);
331 TuiFillArea(Right, Top, Right, Top, URCorner, Attr);
332 TuiFillArea(Left, Bottom, Left, Bottom, LLCorner, Attr);
333 TuiFillArea(Right, Bottom, Right, Bottom, LRCorner, Attr);
334
335 // Fill in left line
336 TuiFillArea(Left, Top+1, Left, Bottom-1, VertStyle, Attr);
337 // Fill in top line
338 TuiFillArea(Left+1, Top, Right-1, Top, HorzStyle, Attr);
339 // Fill in right line
340 TuiFillArea(Right, Top+1, Right, Bottom-1, VertStyle, Attr);
341 // Fill in bottom line
342 TuiFillArea(Left+1, Bottom, Right-1, Bottom, HorzStyle, Attr);
343
344 // Draw the shadow
345 if (Shadow)
346 {
347 TuiDrawShadow(Left, Top, Right, Bottom);
348 }
349 }
350
351 /*
352 * DrawText()
353 * This function assumes coordinates are zero-based
354 */
355 VOID TuiDrawText(ULONG X, ULONG Y, PCSTR Text, UCHAR Attr)
356 {
357 PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer;
358 ULONG i, j;
359
360 // Draw the text
361 for (i=X, j=0; Text[j] && i<UiScreenWidth; i++,j++)
362 {
363 ScreenMemory[((Y*2)*UiScreenWidth)+(i*2)] = (UCHAR)Text[j];
364 ScreenMemory[((Y*2)*UiScreenWidth)+(i*2)+1] = Attr;
365 }
366 }
367
368 VOID TuiDrawCenteredText(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, PCSTR TextString, UCHAR Attr)
369 {
370 ULONG TextLength;
371 ULONG BoxWidth;
372 ULONG BoxHeight;
373 ULONG LineBreakCount;
374 ULONG Index;
375 ULONG LastIndex;
376 ULONG RealLeft;
377 ULONG RealTop;
378 ULONG X;
379 ULONG Y;
380 CHAR Temp[2];
381
382 TextLength = strlen(TextString);
383
384 // Count the new lines and the box width
385 LineBreakCount = 0;
386 BoxWidth = 0;
387 LastIndex = 0;
388 for (Index=0; Index<TextLength; Index++)
389 {
390 if (TextString[Index] == '\n')
391 {
392 LastIndex = Index;
393 LineBreakCount++;
394 }
395 else
396 {
397 if ((Index - LastIndex) > BoxWidth)
398 {
399 BoxWidth = (Index - LastIndex);
400 }
401 }
402 }
403
404 BoxHeight = LineBreakCount + 1;
405
406 RealLeft = (((Right - Left) - BoxWidth) / 2) + Left;
407 RealTop = (((Bottom - Top) - BoxHeight) / 2) + Top;
408
409 LastIndex = 0;
410 for (Index=0; Index<TextLength; Index++)
411 {
412 if (TextString[Index] == '\n')
413 {
414 RealTop++;
415 LastIndex = 0;
416 }
417 else
418 {
419 X = RealLeft + LastIndex;
420 Y = RealTop;
421 LastIndex++;
422 Temp[0] = TextString[Index];
423 Temp[1] = 0;
424 TuiDrawText(X, Y, Temp, Attr);
425 }
426 }
427 }
428
429 VOID TuiDrawStatusText(PCSTR StatusText)
430 {
431 ULONG i;
432
433 TuiDrawText(0, UiScreenHeight-1, " ", ATTR(UiStatusBarFgColor, UiStatusBarBgColor));
434 TuiDrawText(1, UiScreenHeight-1, StatusText, ATTR(UiStatusBarFgColor, UiStatusBarBgColor));
435
436 for (i=strlen(StatusText)+1; i<UiScreenWidth; i++)
437 {
438 TuiDrawText(i, UiScreenHeight-1, " ", ATTR(UiStatusBarFgColor, UiStatusBarBgColor));
439 }
440
441 VideoCopyOffScreenBufferToVRAM();
442 }
443
444 VOID TuiUpdateDateTime(VOID)
445 {
446 ULONG Year, Month, Day;
447 ULONG Hour, Minute, Second;
448 CHAR DateString[40];
449 CHAR TimeString[40];
450 CHAR TempString[20];
451 BOOL PMHour = FALSE;
452
453 MachRTCGetCurrentDateTime(&Year, &Month, &Day, &Hour, &Minute, &Second);
454 if (Year < 1 || 9999 < Year || Month < 1 || 12 < Month || Day < 1 ||
455 31 < Day || 23 < Hour || 59 < Minute || 59 < Second)
456 {
457 /* This happens on QEmu sometimes. We just skip updating */
458 return;
459 }
460 // Get the month name
461 strcpy(DateString, UiMonthNames[Month - 1]);
462 // Get the day
463 _itoa(Day, TempString, 10);
464 // Get the day postfix
465 if (1 == Day || 21 == Day || 31 == Day)
466 {
467 strcat(TempString, "st");
468 }
469 else if (2 == Day || 22 == Day)
470 {
471 strcat(TempString, "nd");
472 }
473 else if (3 == Day || 23 == Day)
474 {
475 strcat(TempString, "rd");
476 }
477 else
478 {
479 strcat(TempString, "th");
480 }
481
482 // Add the day to the date
483 strcat(DateString, TempString);
484 strcat(DateString, " ");
485
486 // Get the year and add it to the date
487 _itoa(Year, TempString, 10);
488 strcat(DateString, TempString);
489
490 // Draw the date
491 TuiDrawText(UiScreenWidth-strlen(DateString)-2, 1, DateString, ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
492
493 // Get the hour and change from 24-hour mode to 12-hour
494 if (Hour > 12)
495 {
496 Hour -= 12;
497 PMHour = TRUE;
498 }
499 if (Hour == 0)
500 {
501 Hour = 12;
502 }
503 _itoa(Hour, TempString, 10);
504 strcpy(TimeString, " ");
505 strcat(TimeString, TempString);
506 strcat(TimeString, ":");
507 _itoa(Minute, TempString, 10);
508 if (Minute < 10)
509 {
510 strcat(TimeString, "0");
511 }
512 strcat(TimeString, TempString);
513 strcat(TimeString, ":");
514 _itoa(Second, TempString, 10);
515 if (Second < 10)
516 {
517 strcat(TimeString, "0");
518 }
519 strcat(TimeString, TempString);
520 if (PMHour)
521 {
522 strcat(TimeString, " PM");
523 }
524 else
525 {
526 strcat(TimeString, " AM");
527 }
528
529 // Draw the time
530 TuiDrawText(UiScreenWidth-strlen(TimeString)-2, 2, TimeString, ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
531 }
532
533 VOID TuiSaveScreen(PUCHAR Buffer)
534 {
535 PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer;
536 ULONG i;
537
538 for (i=0; i < (UiScreenWidth * UiScreenHeight * 2); i++)
539 {
540 Buffer[i] = ScreenMemory[i];
541 }
542 }
543
544 VOID TuiRestoreScreen(PUCHAR Buffer)
545 {
546 PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer;
547 ULONG i;
548
549 for (i=0; i < (UiScreenWidth * UiScreenHeight * 2); i++)
550 {
551 ScreenMemory[i] = Buffer[i];
552 }
553 }
554
555 VOID TuiMessageBox(PCSTR MessageText)
556 {
557 PVOID ScreenBuffer;
558
559 // Save the screen contents
560 ScreenBuffer = MmAllocateMemory(UiScreenWidth * UiScreenHeight * 2);
561 TuiSaveScreen(ScreenBuffer);
562
563 // Display the message box
564 TuiMessageBoxCritical(MessageText);
565
566 // Restore the screen contents
567 TuiRestoreScreen(ScreenBuffer);
568 MmFreeMemory(ScreenBuffer);
569 }
570
571 VOID TuiMessageBoxCritical(PCSTR MessageText)
572 {
573 int width = 8;
574 unsigned int height = 1;
575 int curline = 0;
576 int k;
577 size_t i , j;
578 int x1, x2, y1, y2;
579 char temp[260];
580 char key;
581
582 // Find the height
583 for (i=0; i<strlen(MessageText); i++)
584 {
585 if (MessageText[i] == '\n')
586 height++;
587 }
588
589 // Find the width
590 for (i=0,j=0,k=0; i<height; i++)
591 {
592 while ((MessageText[j] != '\n') && (MessageText[j] != 0))
593 {
594 j++;
595 k++;
596 }
597
598 if (k > width)
599 width = k;
600
601 k = 0;
602 j++;
603 }
604
605 // Calculate box area
606 x1 = (UiScreenWidth - (width+2))/2;
607 x2 = x1 + width + 3;
608 y1 = ((UiScreenHeight - height - 2)/2) + 1;
609 y2 = y1 + height + 4;
610
611 // Draw the box
612 TuiDrawBox(x1, y1, x2, y2, D_VERT, D_HORZ, TRUE, TRUE, ATTR(UiMessageBoxFgColor, UiMessageBoxBgColor));
613
614 // Draw the text
615 for (i=0,j=0; i<strlen(MessageText)+1; i++)
616 {
617 if ((MessageText[i] == '\n') || (MessageText[i] == 0))
618 {
619 temp[j] = 0;
620 j = 0;
621 UiDrawText(x1+2, y1+1+curline, temp, ATTR(UiMessageBoxFgColor, UiMessageBoxBgColor));
622 curline++;
623 }
624 else
625 temp[j++] = MessageText[i];
626 }
627
628 // Draw OK button
629 strcpy(temp, " OK ");
630 UiDrawText(x1+((x2-x1)/2)-3, y2-2, temp, ATTR(COLOR_BLACK, COLOR_GRAY));
631
632 // Draw status text
633 UiDrawStatusText("Press ENTER to continue");
634
635 VideoCopyOffScreenBufferToVRAM();
636
637 for (;;)
638 {
639 if (MachConsKbHit())
640 {
641 key = MachConsGetCh();
642 if(key == KEY_EXTENDED)
643 key = MachConsGetCh();
644
645 if(key == KEY_ENTER)
646 break;
647 else if(key == KEY_SPACE)
648 break;
649 else if(key == KEY_ESC)
650 break;
651 }
652
653 TuiUpdateDateTime();
654
655 VideoCopyOffScreenBufferToVRAM();
656 }
657
658 }
659
660
661 VOID TuiDrawProgressBarCenter(ULONG Position, ULONG Range, PCHAR ProgressText)
662 {
663 ULONG Left, Top, Right, Bottom;
664 ULONG Width = 50; // Allow for 50 "bars"
665 ULONG Height = 2;
666
667 Left = (UiScreenWidth - Width - 4) / 2;
668 Right = Left + Width + 3;
669 Top = (UiScreenHeight - Height - 2) / 2;
670 Top += 2;
671 Bottom = Top + Height + 1;
672
673 TuiDrawProgressBar(Left, Top, Right, Bottom, Position, Range, ProgressText);
674 }
675
676 VOID TuiDrawProgressBar(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, ULONG Position, ULONG Range, PCHAR ProgressText)
677 {
678 ULONG i;
679 ULONG ProgressBarWidth = (Right - Left) - 3;
680
681 // First make sure the progress bar text fits
682 UiTruncateStringEllipsis(ProgressText, ProgressBarWidth - 4);
683
684 if (Position > Range)
685 {
686 Position = Range;
687 }
688
689 // Draw the box
690 TuiDrawBox(Left, Top, Right, Bottom, VERT, HORZ, TRUE, TRUE, ATTR(UiMenuFgColor, UiMenuBgColor));
691
692 // Draw the "Loading..." text
693 //TuiDrawText(70/2, Top+1, "Loading...", ATTR(UiTextColor, UiMenuBgColor));
694 TuiDrawCenteredText(Left + 2, Top + 2, Right - 2, Top + 2, ProgressText, ATTR(UiTextColor, UiMenuBgColor));
695
696 // Draw the percent complete
697 for (i=0; i<(Position*ProgressBarWidth)/Range; i++)
698 {
699 TuiDrawText(Left+2+i, Top+2, "\xDB", ATTR(UiTextColor, UiMenuBgColor));
700 }
701
702 // Draw the rest
703 for (; i<ProgressBarWidth; i++)
704 {
705 TuiDrawText(Left+2+i, Top+2, "\xB2", ATTR(UiTextColor, UiMenuBgColor));
706 }
707
708 TuiUpdateDateTime();
709
710 VideoCopyOffScreenBufferToVRAM();
711 }
712
713 UCHAR TuiTextToColor(PCSTR ColorText)
714 {
715 if (_stricmp(ColorText, "Black") == 0)
716 return COLOR_BLACK;
717 else if (_stricmp(ColorText, "Blue") == 0)
718 return COLOR_BLUE;
719 else if (_stricmp(ColorText, "Green") == 0)
720 return COLOR_GREEN;
721 else if (_stricmp(ColorText, "Cyan") == 0)
722 return COLOR_CYAN;
723 else if (_stricmp(ColorText, "Red") == 0)
724 return COLOR_RED;
725 else if (_stricmp(ColorText, "Magenta") == 0)
726 return COLOR_MAGENTA;
727 else if (_stricmp(ColorText, "Brown") == 0)
728 return COLOR_BROWN;
729 else if (_stricmp(ColorText, "Gray") == 0)
730 return COLOR_GRAY;
731 else if (_stricmp(ColorText, "DarkGray") == 0)
732 return COLOR_DARKGRAY;
733 else if (_stricmp(ColorText, "LightBlue") == 0)
734 return COLOR_LIGHTBLUE;
735 else if (_stricmp(ColorText, "LightGreen") == 0)
736 return COLOR_LIGHTGREEN;
737 else if (_stricmp(ColorText, "LightCyan") == 0)
738 return COLOR_LIGHTCYAN;
739 else if (_stricmp(ColorText, "LightRed") == 0)
740 return COLOR_LIGHTRED;
741 else if (_stricmp(ColorText, "LightMagenta") == 0)
742 return COLOR_LIGHTMAGENTA;
743 else if (_stricmp(ColorText, "Yellow") == 0)
744 return COLOR_YELLOW;
745 else if (_stricmp(ColorText, "White") == 0)
746 return COLOR_WHITE;
747
748 return COLOR_BLACK;
749 }
750
751 UCHAR TuiTextToFillStyle(PCSTR FillStyleText)
752 {
753 if (_stricmp(FillStyleText, "Light") == 0)
754 {
755 return LIGHT_FILL;
756 }
757 else if (_stricmp(FillStyleText, "Medium") == 0)
758 {
759 return MEDIUM_FILL;
760 }
761 else if (_stricmp(FillStyleText, "Dark") == 0)
762 {
763 return DARK_FILL;
764 }
765
766 return LIGHT_FILL;
767 }
768
769 VOID TuiFadeInBackdrop(VOID)
770 {
771 PPALETTE_ENTRY TuiFadePalette = NULL;
772
773 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed())
774 {
775 TuiFadePalette = (PPALETTE_ENTRY)MmAllocateMemory(sizeof(PALETTE_ENTRY) * 64);
776
777 if (TuiFadePalette != NULL)
778 {
779 VideoSavePaletteState(TuiFadePalette, 64);
780 VideoSetAllColorsToBlack(64);
781 }
782 }
783
784 // Draw the backdrop and title box
785 TuiDrawBackdrop();
786
787 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed() && TuiFadePalette != NULL)
788 {
789 VideoFadeIn(TuiFadePalette, 64);
790 MmFreeMemory(TuiFadePalette);
791 }
792 }
793
794 VOID TuiFadeOut(VOID)
795 {
796 PPALETTE_ENTRY TuiFadePalette = NULL;
797
798 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed())
799 {
800 TuiFadePalette = (PPALETTE_ENTRY)MmAllocateMemory(sizeof(PALETTE_ENTRY) * 64);
801
802 if (TuiFadePalette != NULL)
803 {
804 VideoSavePaletteState(TuiFadePalette, 64);
805 }
806 }
807
808 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed() && TuiFadePalette != NULL)
809 {
810 VideoFadeOut(64);
811 }
812
813 MachVideoSetDisplayMode(NULL, FALSE);
814
815 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed() && TuiFadePalette != NULL)
816 {
817 VideoRestorePaletteState(TuiFadePalette, 64);
818 MmFreeMemory(TuiFadePalette);
819 }
820
821 }
822
823 BOOL TuiEditBox(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length)
824 {
825 int width = 8;
826 unsigned int height = 1;
827 int curline = 0;
828 int k;
829 size_t i , j;
830 int x1, x2, y1, y2;
831 char temp[260];
832 char key;
833 int EditBoxLine;
834 ULONG EditBoxStartX, EditBoxEndX;
835 int EditBoxCursorX;
836 unsigned int EditBoxTextCount;
837 int EditBoxTextDisplayIndex;
838 BOOL ReturnCode;
839 PVOID ScreenBuffer;
840
841 // Save the screen contents
842 ScreenBuffer = MmAllocateMemory(UiScreenWidth * UiScreenHeight * 2);
843 TuiSaveScreen(ScreenBuffer);
844
845 // Find the height
846 for (i=0; i<strlen(MessageText); i++)
847 {
848 if (MessageText[i] == '\n')
849 height++;
850 }
851
852 // Find the width
853 for (i=0,j=0,k=0; i<height; i++)
854 {
855 while ((MessageText[j] != '\n') && (MessageText[j] != 0))
856 {
857 j++;
858 k++;
859 }
860
861 if (k > width)
862 width = k;
863
864 k = 0;
865 j++;
866 }
867
868 // Calculate box area
869 x1 = (UiScreenWidth - (width+2))/2;
870 x2 = x1 + width + 3;
871 y1 = ((UiScreenHeight - height - 2)/2) + 1;
872 y2 = y1 + height + 4;
873
874 // Draw the box
875 TuiDrawBox(x1, y1, x2, y2, D_VERT, D_HORZ, TRUE, TRUE, ATTR(UiMessageBoxFgColor, UiMessageBoxBgColor));
876
877 // Draw the text
878 for (i=0,j=0; i<strlen(MessageText)+1; i++)
879 {
880 if ((MessageText[i] == '\n') || (MessageText[i] == 0))
881 {
882 temp[j] = 0;
883 j = 0;
884 UiDrawText(x1+2, y1+1+curline, temp, ATTR(UiMessageBoxFgColor, UiMessageBoxBgColor));
885 curline++;
886 }
887 else
888 temp[j++] = MessageText[i];
889 }
890
891 EditBoxTextCount = 0;
892 EditBoxLine = y2 - 2;
893 EditBoxStartX = x1 + 3;
894 EditBoxEndX = x2 - 3;
895 UiFillArea(EditBoxStartX, EditBoxLine, EditBoxEndX, EditBoxLine, ' ', ATTR(UiEditBoxTextColor, UiEditBoxBgColor));
896
897 // Show the cursor
898 EditBoxCursorX = EditBoxStartX;
899 MachVideoSetTextCursorPosition(EditBoxCursorX, EditBoxLine);
900 MachVideoHideShowTextCursor(TRUE);
901
902 // Draw status text
903 UiDrawStatusText("Press ENTER to continue, or ESC to cancel");
904
905 VideoCopyOffScreenBufferToVRAM();
906
907 for (;;)
908 {
909 if (MachConsKbHit())
910 {
911 key = MachConsGetCh();
912 if(key == KEY_EXTENDED)
913 {
914 key = MachConsGetCh();
915 }
916
917 if(key == KEY_ENTER)
918 {
919 ReturnCode = TRUE;
920 break;
921 }
922 else if(key == KEY_ESC)
923 {
924 ReturnCode = FALSE;
925 break;
926 }
927 else if (key == KEY_BACKSPACE) // Remove a character
928 {
929 if (EditBoxTextCount)
930 {
931 EditBoxTextCount--;
932 EditTextBuffer[EditBoxTextCount] = 0;
933 }
934 else
935 {
936 beep();
937 }
938 }
939 else // Add this key to the buffer
940 {
941 if (EditBoxTextCount < Length - 1)
942 {
943 EditTextBuffer[EditBoxTextCount] = key;
944 EditBoxTextCount++;
945 EditTextBuffer[EditBoxTextCount] = 0;
946 }
947 else
948 {
949 beep();
950 }
951 }
952 }
953
954 // Draw the edit box background
955 UiFillArea(EditBoxStartX, EditBoxLine, EditBoxEndX, EditBoxLine, ' ', ATTR(UiEditBoxTextColor, UiEditBoxBgColor));
956
957 // Fill the text in
958 if (EditBoxTextCount > (EditBoxEndX - EditBoxStartX))
959 {
960 EditBoxTextDisplayIndex = EditBoxTextCount - (EditBoxEndX - EditBoxStartX);
961 EditBoxCursorX = EditBoxEndX;
962 }
963 else
964 {
965 EditBoxTextDisplayIndex = 0;
966 EditBoxCursorX = EditBoxStartX + EditBoxTextCount;
967 }
968 UiDrawText(EditBoxStartX, EditBoxLine, &EditTextBuffer[EditBoxTextDisplayIndex], ATTR(UiEditBoxTextColor, UiEditBoxBgColor));
969
970 // Move the cursor
971 MachVideoSetTextCursorPosition(EditBoxCursorX, EditBoxLine);
972
973 TuiUpdateDateTime();
974
975 VideoCopyOffScreenBufferToVRAM();
976 }
977
978 // Hide the cursor again
979 MachVideoHideShowTextCursor(FALSE);
980
981 // Restore the screen contents
982 TuiRestoreScreen(ScreenBuffer);
983 MmFreeMemory(ScreenBuffer);
984
985 return ReturnCode;
986 }