Fix the clipping checks in TuiFillArea.
[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 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, BOOL Fill, BOOL 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 BOOL PMHour = FALSE;
451
452 MachRTCGetCurrentDateTime(&Year, &Month, &Day, &Hour, &Minute, &Second);
453 if (Year < 1 || 9999 < Year || Month < 1 || 12 < Month || Day < 1 ||
454 31 < Day || 23 < Hour || 59 < Minute || 59 < Second)
455 {
456 /* This happens on QEmu sometimes. We just skip updating */
457 return;
458 }
459 // Get the month name
460 strcpy(DateString, UiMonthNames[Month - 1]);
461 // Get the day
462 _itoa(Day, TempString, 10);
463 // Get the day postfix
464 if (1 == Day || 21 == Day || 31 == Day)
465 {
466 strcat(TempString, "st");
467 }
468 else if (2 == Day || 22 == Day)
469 {
470 strcat(TempString, "nd");
471 }
472 else if (3 == Day || 23 == Day)
473 {
474 strcat(TempString, "rd");
475 }
476 else
477 {
478 strcat(TempString, "th");
479 }
480
481 // Add the day to the date
482 strcat(DateString, TempString);
483 strcat(DateString, " ");
484
485 // Get the year and add it to the date
486 _itoa(Year, TempString, 10);
487 strcat(DateString, TempString);
488
489 // Draw the date
490 TuiDrawText(UiScreenWidth-strlen(DateString)-2, 1, DateString, ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
491
492 // Get the hour and change from 24-hour mode to 12-hour
493 if (Hour > 12)
494 {
495 Hour -= 12;
496 PMHour = TRUE;
497 }
498 if (Hour == 0)
499 {
500 Hour = 12;
501 }
502 _itoa(Hour, TempString, 10);
503 strcpy(TimeString, " ");
504 strcat(TimeString, TempString);
505 strcat(TimeString, ":");
506 _itoa(Minute, TempString, 10);
507 if (Minute < 10)
508 {
509 strcat(TimeString, "0");
510 }
511 strcat(TimeString, TempString);
512 strcat(TimeString, ":");
513 _itoa(Second, TempString, 10);
514 if (Second < 10)
515 {
516 strcat(TimeString, "0");
517 }
518 strcat(TimeString, TempString);
519 if (PMHour)
520 {
521 strcat(TimeString, " PM");
522 }
523 else
524 {
525 strcat(TimeString, " AM");
526 }
527
528 // Draw the time
529 TuiDrawText(UiScreenWidth-strlen(TimeString)-2, 2, TimeString, ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
530 }
531
532 VOID TuiSaveScreen(PUCHAR Buffer)
533 {
534 PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer;
535 ULONG i;
536
537 for (i=0; i < (UiScreenWidth * UiScreenHeight * 2); i++)
538 {
539 Buffer[i] = ScreenMemory[i];
540 }
541 }
542
543 VOID TuiRestoreScreen(PUCHAR Buffer)
544 {
545 PUCHAR ScreenMemory = (PUCHAR)TextVideoBuffer;
546 ULONG i;
547
548 for (i=0; i < (UiScreenWidth * UiScreenHeight * 2); i++)
549 {
550 ScreenMemory[i] = Buffer[i];
551 }
552 }
553
554 VOID TuiMessageBox(PCSTR MessageText)
555 {
556 PVOID ScreenBuffer;
557
558 // Save the screen contents
559 ScreenBuffer = MmAllocateMemory(UiScreenWidth * UiScreenHeight * 2);
560 TuiSaveScreen(ScreenBuffer);
561
562 // Display the message box
563 TuiMessageBoxCritical(MessageText);
564
565 // Restore the screen contents
566 TuiRestoreScreen(ScreenBuffer);
567 MmFreeMemory(ScreenBuffer);
568 }
569
570 VOID TuiMessageBoxCritical(PCSTR MessageText)
571 {
572 int width = 8;
573 unsigned int height = 1;
574 int curline = 0;
575 int k;
576 size_t i , j;
577 int x1, x2, y1, y2;
578 char temp[260];
579 char key;
580
581 // Find the height
582 for (i=0; i<strlen(MessageText); i++)
583 {
584 if (MessageText[i] == '\n')
585 height++;
586 }
587
588 // Find the width
589 for (i=0,j=0,k=0; i<height; i++)
590 {
591 while ((MessageText[j] != '\n') && (MessageText[j] != 0))
592 {
593 j++;
594 k++;
595 }
596
597 if (k > width)
598 width = k;
599
600 k = 0;
601 j++;
602 }
603
604 // Calculate box area
605 x1 = (UiScreenWidth - (width+2))/2;
606 x2 = x1 + width + 3;
607 y1 = ((UiScreenHeight - height - 2)/2) + 1;
608 y2 = y1 + height + 4;
609
610 // Draw the box
611 TuiDrawBox(x1, y1, x2, y2, D_VERT, D_HORZ, TRUE, TRUE, ATTR(UiMessageBoxFgColor, UiMessageBoxBgColor));
612
613 // Draw the text
614 for (i=0,j=0; i<strlen(MessageText)+1; i++)
615 {
616 if ((MessageText[i] == '\n') || (MessageText[i] == 0))
617 {
618 temp[j] = 0;
619 j = 0;
620 UiDrawText(x1+2, y1+1+curline, temp, ATTR(UiMessageBoxFgColor, UiMessageBoxBgColor));
621 curline++;
622 }
623 else
624 temp[j++] = MessageText[i];
625 }
626
627 // Draw OK button
628 strcpy(temp, " OK ");
629 UiDrawText(x1+((x2-x1)/2)-3, y2-2, temp, ATTR(COLOR_BLACK, COLOR_GRAY));
630
631 // Draw status text
632 UiDrawStatusText("Press ENTER to continue");
633
634 VideoCopyOffScreenBufferToVRAM();
635
636 for (;;)
637 {
638 if (MachConsKbHit())
639 {
640 key = MachConsGetCh();
641 if(key == KEY_EXTENDED)
642 key = MachConsGetCh();
643
644 if(key == KEY_ENTER)
645 break;
646 else if(key == KEY_SPACE)
647 break;
648 else if(key == KEY_ESC)
649 break;
650 }
651
652 TuiUpdateDateTime();
653
654 VideoCopyOffScreenBufferToVRAM();
655 }
656
657 }
658
659
660 VOID TuiDrawProgressBarCenter(ULONG Position, ULONG Range, PCHAR ProgressText)
661 {
662 ULONG Left, Top, Right, Bottom;
663 ULONG Width = 50; // Allow for 50 "bars"
664 ULONG Height = 2;
665
666 Left = (UiScreenWidth - Width - 4) / 2;
667 Right = Left + Width + 3;
668 Top = (UiScreenHeight - Height - 2) / 2;
669 Top += 2;
670 Bottom = Top + Height + 1;
671
672 TuiDrawProgressBar(Left, Top, Right, Bottom, Position, Range, ProgressText);
673 }
674
675 VOID TuiDrawProgressBar(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, ULONG Position, ULONG Range, PCHAR ProgressText)
676 {
677 ULONG i;
678 ULONG ProgressBarWidth = (Right - Left) - 3;
679
680 // First make sure the progress bar text fits
681 UiTruncateStringEllipsis(ProgressText, ProgressBarWidth - 4);
682
683 if (Position > Range)
684 {
685 Position = Range;
686 }
687
688 // Draw the box
689 TuiDrawBox(Left, Top, Right, Bottom, VERT, HORZ, TRUE, TRUE, ATTR(UiMenuFgColor, UiMenuBgColor));
690
691 // Draw the "Loading..." text
692 //TuiDrawText(70/2, Top+1, "Loading...", ATTR(UiTextColor, UiMenuBgColor));
693 TuiDrawCenteredText(Left + 2, Top + 2, Right - 2, Top + 2, ProgressText, ATTR(UiTextColor, UiMenuBgColor));
694
695 // Draw the percent complete
696 for (i=0; i<(Position*ProgressBarWidth)/Range; i++)
697 {
698 TuiDrawText(Left+2+i, Top+2, "\xDB", ATTR(UiTextColor, UiMenuBgColor));
699 }
700
701 // Draw the rest
702 for (; i<ProgressBarWidth; i++)
703 {
704 TuiDrawText(Left+2+i, Top+2, "\xB2", ATTR(UiTextColor, UiMenuBgColor));
705 }
706
707 TuiUpdateDateTime();
708
709 VideoCopyOffScreenBufferToVRAM();
710 }
711
712 UCHAR TuiTextToColor(PCSTR ColorText)
713 {
714 if (_stricmp(ColorText, "Black") == 0)
715 return COLOR_BLACK;
716 else if (_stricmp(ColorText, "Blue") == 0)
717 return COLOR_BLUE;
718 else if (_stricmp(ColorText, "Green") == 0)
719 return COLOR_GREEN;
720 else if (_stricmp(ColorText, "Cyan") == 0)
721 return COLOR_CYAN;
722 else if (_stricmp(ColorText, "Red") == 0)
723 return COLOR_RED;
724 else if (_stricmp(ColorText, "Magenta") == 0)
725 return COLOR_MAGENTA;
726 else if (_stricmp(ColorText, "Brown") == 0)
727 return COLOR_BROWN;
728 else if (_stricmp(ColorText, "Gray") == 0)
729 return COLOR_GRAY;
730 else if (_stricmp(ColorText, "DarkGray") == 0)
731 return COLOR_DARKGRAY;
732 else if (_stricmp(ColorText, "LightBlue") == 0)
733 return COLOR_LIGHTBLUE;
734 else if (_stricmp(ColorText, "LightGreen") == 0)
735 return COLOR_LIGHTGREEN;
736 else if (_stricmp(ColorText, "LightCyan") == 0)
737 return COLOR_LIGHTCYAN;
738 else if (_stricmp(ColorText, "LightRed") == 0)
739 return COLOR_LIGHTRED;
740 else if (_stricmp(ColorText, "LightMagenta") == 0)
741 return COLOR_LIGHTMAGENTA;
742 else if (_stricmp(ColorText, "Yellow") == 0)
743 return COLOR_YELLOW;
744 else if (_stricmp(ColorText, "White") == 0)
745 return COLOR_WHITE;
746
747 return COLOR_BLACK;
748 }
749
750 UCHAR TuiTextToFillStyle(PCSTR FillStyleText)
751 {
752 if (_stricmp(FillStyleText, "Light") == 0)
753 {
754 return LIGHT_FILL;
755 }
756 else if (_stricmp(FillStyleText, "Medium") == 0)
757 {
758 return MEDIUM_FILL;
759 }
760 else if (_stricmp(FillStyleText, "Dark") == 0)
761 {
762 return DARK_FILL;
763 }
764
765 return LIGHT_FILL;
766 }
767
768 VOID TuiFadeInBackdrop(VOID)
769 {
770 PPALETTE_ENTRY TuiFadePalette = NULL;
771
772 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed())
773 {
774 TuiFadePalette = (PPALETTE_ENTRY)MmAllocateMemory(sizeof(PALETTE_ENTRY) * 64);
775
776 if (TuiFadePalette != NULL)
777 {
778 VideoSavePaletteState(TuiFadePalette, 64);
779 VideoSetAllColorsToBlack(64);
780 }
781 }
782
783 // Draw the backdrop and title box
784 TuiDrawBackdrop();
785
786 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed() && TuiFadePalette != NULL)
787 {
788 VideoFadeIn(TuiFadePalette, 64);
789 MmFreeMemory(TuiFadePalette);
790 }
791 }
792
793 VOID TuiFadeOut(VOID)
794 {
795 PPALETTE_ENTRY TuiFadePalette = NULL;
796
797 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed())
798 {
799 TuiFadePalette = (PPALETTE_ENTRY)MmAllocateMemory(sizeof(PALETTE_ENTRY) * 64);
800
801 if (TuiFadePalette != NULL)
802 {
803 VideoSavePaletteState(TuiFadePalette, 64);
804 }
805 }
806
807 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed() && TuiFadePalette != NULL)
808 {
809 VideoFadeOut(64);
810 }
811
812 MachVideoSetDisplayMode(NULL, FALSE);
813
814 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed() && TuiFadePalette != NULL)
815 {
816 VideoRestorePaletteState(TuiFadePalette, 64);
817 MmFreeMemory(TuiFadePalette);
818 }
819
820 }
821
822 BOOL TuiEditBox(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length)
823 {
824 int width = 8;
825 unsigned int height = 1;
826 int curline = 0;
827 int k;
828 size_t i , j;
829 int x1, x2, y1, y2;
830 char temp[260];
831 char key;
832 int EditBoxLine;
833 ULONG EditBoxStartX, EditBoxEndX;
834 int EditBoxCursorX;
835 unsigned int EditBoxTextCount;
836 int EditBoxTextDisplayIndex;
837 BOOL ReturnCode;
838 PVOID ScreenBuffer;
839
840 // Save the screen contents
841 ScreenBuffer = MmAllocateMemory(UiScreenWidth * UiScreenHeight * 2);
842 TuiSaveScreen(ScreenBuffer);
843
844 // Find the height
845 for (i=0; i<strlen(MessageText); i++)
846 {
847 if (MessageText[i] == '\n')
848 height++;
849 }
850
851 // Find the width
852 for (i=0,j=0,k=0; i<height; i++)
853 {
854 while ((MessageText[j] != '\n') && (MessageText[j] != 0))
855 {
856 j++;
857 k++;
858 }
859
860 if (k > width)
861 width = k;
862
863 k = 0;
864 j++;
865 }
866
867 // Calculate box area
868 x1 = (UiScreenWidth - (width+2))/2;
869 x2 = x1 + width + 3;
870 y1 = ((UiScreenHeight - height - 2)/2) + 1;
871 y2 = y1 + height + 4;
872
873 // Draw the box
874 TuiDrawBox(x1, y1, x2, y2, D_VERT, D_HORZ, TRUE, TRUE, ATTR(UiMessageBoxFgColor, UiMessageBoxBgColor));
875
876 // Draw the text
877 for (i=0,j=0; i<strlen(MessageText)+1; i++)
878 {
879 if ((MessageText[i] == '\n') || (MessageText[i] == 0))
880 {
881 temp[j] = 0;
882 j = 0;
883 UiDrawText(x1+2, y1+1+curline, temp, ATTR(UiMessageBoxFgColor, UiMessageBoxBgColor));
884 curline++;
885 }
886 else
887 temp[j++] = MessageText[i];
888 }
889
890 EditBoxTextCount = 0;
891 EditBoxLine = y2 - 2;
892 EditBoxStartX = x1 + 3;
893 EditBoxEndX = x2 - 3;
894 UiFillArea(EditBoxStartX, EditBoxLine, EditBoxEndX, EditBoxLine, ' ', ATTR(UiEditBoxTextColor, UiEditBoxBgColor));
895
896 // Show the cursor
897 EditBoxCursorX = EditBoxStartX;
898 MachVideoSetTextCursorPosition(EditBoxCursorX, EditBoxLine);
899 MachVideoHideShowTextCursor(TRUE);
900
901 // Draw status text
902 UiDrawStatusText("Press ENTER to continue, or ESC to cancel");
903
904 VideoCopyOffScreenBufferToVRAM();
905
906 for (;;)
907 {
908 if (MachConsKbHit())
909 {
910 key = MachConsGetCh();
911 if(key == KEY_EXTENDED)
912 {
913 key = MachConsGetCh();
914 }
915
916 if(key == KEY_ENTER)
917 {
918 ReturnCode = TRUE;
919 break;
920 }
921 else if(key == KEY_ESC)
922 {
923 ReturnCode = FALSE;
924 break;
925 }
926 else if (key == KEY_BACKSPACE) // Remove a character
927 {
928 if (EditBoxTextCount)
929 {
930 EditBoxTextCount--;
931 EditTextBuffer[EditBoxTextCount] = 0;
932 }
933 else
934 {
935 beep();
936 }
937 }
938 else // Add this key to the buffer
939 {
940 if (EditBoxTextCount < Length - 1)
941 {
942 EditTextBuffer[EditBoxTextCount] = key;
943 EditBoxTextCount++;
944 EditTextBuffer[EditBoxTextCount] = 0;
945 }
946 else
947 {
948 beep();
949 }
950 }
951 }
952
953 // Draw the edit box background
954 UiFillArea(EditBoxStartX, EditBoxLine, EditBoxEndX, EditBoxLine, ' ', ATTR(UiEditBoxTextColor, UiEditBoxBgColor));
955
956 // Fill the text in
957 if (EditBoxTextCount > (EditBoxEndX - EditBoxStartX))
958 {
959 EditBoxTextDisplayIndex = EditBoxTextCount - (EditBoxEndX - EditBoxStartX);
960 EditBoxCursorX = EditBoxEndX;
961 }
962 else
963 {
964 EditBoxTextDisplayIndex = 0;
965 EditBoxCursorX = EditBoxStartX + EditBoxTextCount;
966 }
967 UiDrawText(EditBoxStartX, EditBoxLine, &EditTextBuffer[EditBoxTextDisplayIndex], ATTR(UiEditBoxTextColor, UiEditBoxBgColor));
968
969 // Move the cursor
970 MachVideoSetTextCursorPosition(EditBoxCursorX, EditBoxLine);
971
972 TuiUpdateDateTime();
973
974 VideoCopyOffScreenBufferToVRAM();
975 }
976
977 // Hide the cursor again
978 MachVideoHideShowTextCursor(FALSE);
979
980 // Restore the screen contents
981 TuiRestoreScreen(ScreenBuffer);
982 MmFreeMemory(ScreenBuffer);
983
984 return ReturnCode;
985 }