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