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