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