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