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