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