bb4f9e3a8c3ce0a5b907b31e00fd4df1c7ff902d
[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 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
634 VOID TuiDrawProgressBarCenter(ULONG Position, ULONG Range, PCHAR ProgressText)
635 {
636 ULONG Left, Top, Right, Bottom;
637 ULONG Width = 50; // Allow for 50 "bars"
638 ULONG Height = 2;
639
640 Left = (UiScreenWidth - Width - 4) / 2;
641 Right = Left + Width + 3;
642 Top = (UiScreenHeight - Height - 2) / 2;
643 Top += 2;
644 Bottom = Top + Height + 1;
645
646 TuiDrawProgressBar(Left, Top, Right, Bottom, Position, Range, ProgressText);
647 }
648
649 VOID TuiDrawProgressBar(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, ULONG Position, ULONG Range, PCHAR ProgressText)
650 {
651 ULONG i;
652 ULONG ProgressBarWidth = (Right - Left) - 3;
653
654 // First make sure the progress bar text fits
655 UiTruncateStringEllipsis(ProgressText, ProgressBarWidth - 4);
656
657 if (Position > Range)
658 {
659 Position = Range;
660 }
661
662 // Draw the box
663 TuiDrawBox(Left, Top, Right, Bottom, VERT, HORZ, TRUE, TRUE, ATTR(UiMenuFgColor, UiMenuBgColor));
664
665 //
666 // Draw the "Loading..." text
667 //
668 TuiDrawCenteredText(Left + 2, Top + 2, Right - 2, Top + 2, ProgressText, ATTR(UiTextColor, UiMenuBgColor));
669
670 // Draw the percent complete
671 for (i=0; i<(Position*ProgressBarWidth)/Range; i++)
672 {
673 TuiDrawText(Left+2+i, Top+2, "\xDB", ATTR(UiTextColor, UiMenuBgColor));
674 }
675
676 // Draw the shadow
677 for (; i<ProgressBarWidth; i++)
678 {
679 TuiDrawText(Left+2+i, Top+2, "\xB2", ATTR(UiTextColor, UiMenuBgColor));
680 }
681
682 TuiUpdateDateTime();
683 VideoCopyOffScreenBufferToVRAM();
684 }
685
686 UCHAR TuiTextToColor(PCSTR ColorText)
687 {
688 if (_stricmp(ColorText, "Black") == 0)
689 return COLOR_BLACK;
690 else if (_stricmp(ColorText, "Blue") == 0)
691 return COLOR_BLUE;
692 else if (_stricmp(ColorText, "Green") == 0)
693 return COLOR_GREEN;
694 else if (_stricmp(ColorText, "Cyan") == 0)
695 return COLOR_CYAN;
696 else if (_stricmp(ColorText, "Red") == 0)
697 return COLOR_RED;
698 else if (_stricmp(ColorText, "Magenta") == 0)
699 return COLOR_MAGENTA;
700 else if (_stricmp(ColorText, "Brown") == 0)
701 return COLOR_BROWN;
702 else if (_stricmp(ColorText, "Gray") == 0)
703 return COLOR_GRAY;
704 else if (_stricmp(ColorText, "DarkGray") == 0)
705 return COLOR_DARKGRAY;
706 else if (_stricmp(ColorText, "LightBlue") == 0)
707 return COLOR_LIGHTBLUE;
708 else if (_stricmp(ColorText, "LightGreen") == 0)
709 return COLOR_LIGHTGREEN;
710 else if (_stricmp(ColorText, "LightCyan") == 0)
711 return COLOR_LIGHTCYAN;
712 else if (_stricmp(ColorText, "LightRed") == 0)
713 return COLOR_LIGHTRED;
714 else if (_stricmp(ColorText, "LightMagenta") == 0)
715 return COLOR_LIGHTMAGENTA;
716 else if (_stricmp(ColorText, "Yellow") == 0)
717 return COLOR_YELLOW;
718 else if (_stricmp(ColorText, "White") == 0)
719 return COLOR_WHITE;
720
721 return COLOR_BLACK;
722 }
723
724 UCHAR TuiTextToFillStyle(PCSTR FillStyleText)
725 {
726 if (_stricmp(FillStyleText, "Light") == 0)
727 {
728 return LIGHT_FILL;
729 }
730 else if (_stricmp(FillStyleText, "Medium") == 0)
731 {
732 return MEDIUM_FILL;
733 }
734 else if (_stricmp(FillStyleText, "Dark") == 0)
735 {
736 return DARK_FILL;
737 }
738
739 return LIGHT_FILL;
740 }
741
742 VOID TuiFadeInBackdrop(VOID)
743 {
744 PPALETTE_ENTRY TuiFadePalette = NULL;
745
746 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed())
747 {
748 TuiFadePalette = (PPALETTE_ENTRY)MmHeapAlloc(sizeof(PALETTE_ENTRY) * 64);
749
750 if (TuiFadePalette != NULL)
751 {
752 VideoSavePaletteState(TuiFadePalette, 64);
753 VideoSetAllColorsToBlack(64);
754 }
755 }
756
757 // Draw the backdrop and title box
758 TuiDrawBackdrop();
759
760 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed() && TuiFadePalette != NULL)
761 {
762 VideoFadeIn(TuiFadePalette, 64);
763 MmHeapFree(TuiFadePalette);
764 }
765 }
766
767 VOID TuiFadeOut(VOID)
768 {
769 PPALETTE_ENTRY TuiFadePalette = NULL;
770
771 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed())
772 {
773 TuiFadePalette = (PPALETTE_ENTRY)MmHeapAlloc(sizeof(PALETTE_ENTRY) * 64);
774
775 if (TuiFadePalette != NULL)
776 {
777 VideoSavePaletteState(TuiFadePalette, 64);
778 }
779 }
780
781 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed() && TuiFadePalette != NULL)
782 {
783 VideoFadeOut(64);
784 }
785
786 MachVideoSetDisplayMode(NULL, FALSE);
787
788 if (UiUseSpecialEffects && ! MachVideoIsPaletteFixed() && TuiFadePalette != NULL)
789 {
790 VideoRestorePaletteState(TuiFadePalette, 64);
791 MmHeapFree(TuiFadePalette);
792 }
793
794 }
795
796 BOOLEAN TuiEditBox(PCSTR MessageText, PCHAR EditTextBuffer, ULONG Length)
797 {
798 int width = 8;
799 unsigned int height = 1;
800 int curline = 0;
801 int k;
802 size_t i , j;
803 int x1, x2, y1, y2;
804 char temp[260];
805 char key;
806 int EditBoxLine;
807 ULONG EditBoxStartX, EditBoxEndX;
808 int EditBoxCursorX;
809 unsigned int EditBoxTextCount;
810 int EditBoxTextDisplayIndex;
811 BOOLEAN ReturnCode;
812 PVOID ScreenBuffer;
813
814 // Save the screen contents
815 ScreenBuffer = MmHeapAlloc(UiScreenWidth * UiScreenHeight * 2);
816 TuiSaveScreen(ScreenBuffer);
817
818 // Find the height
819 for (i=0; i<strlen(MessageText); i++)
820 {
821 if (MessageText[i] == '\n')
822 height++;
823 }
824
825 // Find the width
826 for (i=0,j=0,k=0; i<height; i++)
827 {
828 while ((MessageText[j] != '\n') && (MessageText[j] != 0))
829 {
830 j++;
831 k++;
832 }
833
834 if (k > width)
835 width = k;
836
837 k = 0;
838 j++;
839 }
840
841 // Calculate box area
842 x1 = (UiScreenWidth - (width+2))/2;
843 x2 = x1 + width + 3;
844 y1 = ((UiScreenHeight - height - 2)/2) + 1;
845 y2 = y1 + height + 4;
846
847 // Draw the box
848 TuiDrawBox(x1, y1, x2, y2, D_VERT, D_HORZ, TRUE, TRUE, ATTR(UiMessageBoxFgColor, UiMessageBoxBgColor));
849
850 // Draw the text
851 for (i=0,j=0; i<strlen(MessageText)+1; i++)
852 {
853 if ((MessageText[i] == '\n') || (MessageText[i] == 0))
854 {
855 temp[j] = 0;
856 j = 0;
857 UiDrawText(x1+2, y1+1+curline, temp, ATTR(UiMessageBoxFgColor, UiMessageBoxBgColor));
858 curline++;
859 }
860 else
861 temp[j++] = MessageText[i];
862 }
863
864 EditBoxTextCount = 0;
865 EditBoxLine = y2 - 2;
866 EditBoxStartX = x1 + 3;
867 EditBoxEndX = x2 - 3;
868 UiFillArea(EditBoxStartX, EditBoxLine, EditBoxEndX, EditBoxLine, ' ', ATTR(UiEditBoxTextColor, UiEditBoxBgColor));
869
870 // Show the cursor
871 EditBoxCursorX = EditBoxStartX;
872 MachVideoSetTextCursorPosition(EditBoxCursorX, EditBoxLine);
873 MachVideoHideShowTextCursor(TRUE);
874
875 // Draw status text
876 UiDrawStatusText("Press ENTER to continue, or ESC to cancel");
877
878 VideoCopyOffScreenBufferToVRAM();
879
880 for (;;)
881 {
882 if (MachConsKbHit())
883 {
884 key = MachConsGetCh();
885 if(key == KEY_EXTENDED)
886 {
887 key = MachConsGetCh();
888 }
889
890 if(key == KEY_ENTER)
891 {
892 ReturnCode = TRUE;
893 break;
894 }
895 else if(key == KEY_ESC)
896 {
897 ReturnCode = FALSE;
898 break;
899 }
900 else if (key == KEY_BACKSPACE) // Remove a character
901 {
902 if (EditBoxTextCount)
903 {
904 EditBoxTextCount--;
905 EditTextBuffer[EditBoxTextCount] = 0;
906 }
907 else
908 {
909 MachBeep();
910 }
911 }
912 else // Add this key to the buffer
913 {
914 if (EditBoxTextCount < Length - 1)
915 {
916 EditTextBuffer[EditBoxTextCount] = key;
917 EditBoxTextCount++;
918 EditTextBuffer[EditBoxTextCount] = 0;
919 }
920 else
921 {
922 MachBeep();
923 }
924 }
925 }
926
927 // Draw the edit box background
928 UiFillArea(EditBoxStartX, EditBoxLine, EditBoxEndX, EditBoxLine, ' ', ATTR(UiEditBoxTextColor, UiEditBoxBgColor));
929
930 // Fill the text in
931 if (EditBoxTextCount > (EditBoxEndX - EditBoxStartX))
932 {
933 EditBoxTextDisplayIndex = EditBoxTextCount - (EditBoxEndX - EditBoxStartX);
934 EditBoxCursorX = EditBoxEndX;
935 }
936 else
937 {
938 EditBoxTextDisplayIndex = 0;
939 EditBoxCursorX = EditBoxStartX + EditBoxTextCount;
940 }
941 UiDrawText(EditBoxStartX, EditBoxLine, &EditTextBuffer[EditBoxTextDisplayIndex], ATTR(UiEditBoxTextColor, UiEditBoxBgColor));
942
943 // Move the cursor
944 MachVideoSetTextCursorPosition(EditBoxCursorX, EditBoxLine);
945
946 TuiUpdateDateTime();
947
948 VideoCopyOffScreenBufferToVRAM();
949
950 MachHwIdle();
951 }
952
953 // Hide the cursor again
954 MachVideoHideShowTextCursor(FALSE);
955
956 // Restore the screen contents
957 TuiRestoreScreen(ScreenBuffer);
958 MmHeapFree(ScreenBuffer);
959
960 return ReturnCode;
961 }
962
963 const UIVTBL TuiVtbl =
964 {
965 TuiInitialize,
966 TuiUnInitialize,
967 TuiDrawBackdrop,
968 TuiFillArea,
969 TuiDrawShadow,
970 TuiDrawBox,
971 TuiDrawText,
972 TuiDrawCenteredText,
973 TuiDrawStatusText,
974 TuiUpdateDateTime,
975 TuiMessageBox,
976 TuiMessageBoxCritical,
977 TuiDrawProgressBarCenter,
978 TuiDrawProgressBar,
979 TuiEditBox,
980 TuiTextToColor,
981 TuiTextToFillStyle,
982 TuiFadeInBackdrop,
983 TuiFadeOut,
984 TuiDisplayMenu,
985 TuiDrawMenu,
986 };
987 #endif