3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
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.
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.
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.
22 PVOID TextVideoBuffer
= NULL
;
24 BOOL
TuiInitialize(VOID
)
26 MachVideoClearScreen(ATTR(COLOR_WHITE
, COLOR_BLACK
));
27 MachVideoHideShowTextCursor(FALSE
);
29 TextVideoBuffer
= VideoAllocateOffScreenBuffer();
30 if (TextVideoBuffer
== NULL
)
38 VOID
TuiUnInitialize(VOID
)
40 if (UiUseSpecialEffects
)
46 MachVideoSetDisplayMode(NULL
, FALSE
);
50 MachVideoHideShowTextCursor(TRUE
);
53 VOID
TuiDrawBackdrop(VOID
)
56 // Fill in the background (excluding title box & status bar)
59 TUI_TITLE_BOX_CHAR_HEIGHT
,
63 ATTR(UiBackdropFgColor
, UiBackdropBgColor
));
71 TUI_TITLE_BOX_CHAR_HEIGHT
- 1,
76 ATTR(UiTitleBoxFgColor
, UiTitleBoxBgColor
));
83 GetFreeLoaderVersionString(),
84 ATTR(UiTitleBoxFgColor
, UiTitleBoxBgColor
));
92 ATTR(UiTitleBoxFgColor
, UiTitleBoxBgColor
));
96 ATTR(UiTitleBoxFgColor
, UiTitleBoxBgColor
));
101 TuiDrawText(UiScreenWidth
- 16, 3, /*"F1 for Help"*/"F8 for Options", ATTR(UiTitleBoxFgColor
, UiTitleBoxBgColor
));
106 TuiDrawText( (UiScreenWidth
/ 2) - (strlen(UiTitleBoxTitleText
) / 2),
109 ATTR(UiTitleBoxFgColor
, UiTitleBoxBgColor
));
114 TuiDrawStatusText("Welcome to FreeLoader!");
117 // Update the date & time
121 VideoCopyOffScreenBufferToVRAM();
126 * This function assumes coordinates are zero-based
128 VOID
TuiFillArea(ULONG Left
, ULONG Top
, ULONG Right
, ULONG Bottom
, CHAR FillChar
, UCHAR Attr
/* Color Attributes */)
130 PUCHAR ScreenMemory
= (PUCHAR
)TextVideoBuffer
;
133 // Clip the area to the screen
134 // FIXME: This code seems to have problems... Uncomment and view ;-)
135 /*if ((Left >= UiScreenWidth) || (Top >= UiScreenHeight))
139 if ((Left + Right) >= UiScreenWidth)
141 Right = UiScreenWidth - Left;
143 if ((Top + Bottom) >= UiScreenHeight)
145 Bottom = UiScreenHeight - Top;
148 // Loop through each line and fill it in
149 for (i
=Top
; i
<=Bottom
; i
++)
151 // Loop through each character (column) in the line and fill it in
152 for (j
=Left
; j
<=Right
; j
++)
154 ScreenMemory
[((i
*2)*UiScreenWidth
)+(j
*2)] = (UCHAR
)FillChar
;
155 ScreenMemory
[((i
*2)*UiScreenWidth
)+(j
*2)+1] = Attr
;
162 * This function assumes coordinates are zero-based
164 VOID
TuiDrawShadow(ULONG Left
, ULONG Top
, ULONG Right
, ULONG Bottom
)
166 PUCHAR ScreenMemory
= (PUCHAR
)TextVideoBuffer
;
169 // Shade the bottom of the area
170 if (Bottom
< (UiScreenHeight
- 1))
172 if (UiScreenHeight
< 34)
181 for (; Idx
<=Right
; Idx
++)
183 ScreenMemory
[(((Bottom
+1)*2)*UiScreenWidth
)+(Idx
*2)+1] = ATTR(COLOR_GRAY
, COLOR_BLACK
);
187 // Shade the right of the area
188 if (Right
< (UiScreenWidth
- 1))
190 for (Idx
=Top
+1; Idx
<=Bottom
; Idx
++)
192 ScreenMemory
[((Idx
*2)*UiScreenWidth
)+((Right
+1)*2)+1] = ATTR(COLOR_GRAY
, COLOR_BLACK
);
195 if (UiScreenHeight
< 34)
197 if ((Right
+ 1) < (UiScreenWidth
- 1))
199 for (Idx
=Top
+1; Idx
<=Bottom
; Idx
++)
201 ScreenMemory
[((Idx
*2)*UiScreenWidth
)+((Right
+2)*2)+1] = ATTR(COLOR_GRAY
, COLOR_BLACK
);
206 // Shade the bottom right corner
207 if ((Right
< (UiScreenWidth
- 1)) && (Bottom
< (UiScreenHeight
- 1)))
209 ScreenMemory
[(((Bottom
+1)*2)*UiScreenWidth
)+((Right
+1)*2)+1] = ATTR(COLOR_GRAY
, COLOR_BLACK
);
211 if (UiScreenHeight
< 34)
213 if (((Right
+ 1) < (UiScreenWidth
- 1)) && (Bottom
< (UiScreenHeight
- 1)))
215 ScreenMemory
[(((Bottom
+1)*2)*UiScreenWidth
)+((Right
+2)*2)+1] = ATTR(COLOR_GRAY
, COLOR_BLACK
);
222 * This function assumes coordinates are zero-based
224 VOID
TuiDrawBox(ULONG Left
, ULONG Top
, ULONG Right
, ULONG Bottom
, UCHAR VertStyle
, UCHAR HorzStyle
, BOOL Fill
, BOOL Shadow
, UCHAR Attr
)
226 UCHAR ULCorner
, URCorner
, LLCorner
, LRCorner
;
228 // Calculate the corner values
229 if (HorzStyle
== HORZ
)
231 if (VertStyle
== VERT
)
238 else // VertStyle == D_VERT
246 else // HorzStyle == D_HORZ
248 if (VertStyle
== VERT
)
255 else // VertStyle == D_VERT
264 // Fill in box background
267 TuiFillArea(Left
, Top
, Right
, Bottom
, ' ', Attr
);
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
);
277 TuiFillArea(Left
, Top
+1, Left
, Bottom
-1, VertStyle
, Attr
);
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
);
288 TuiDrawShadow(Left
, Top
, Right
, Bottom
);
294 * This function assumes coordinates are zero-based
296 VOID
TuiDrawText(ULONG X
, ULONG Y
, PCSTR Text
, UCHAR Attr
)
298 PUCHAR ScreenMemory
= (PUCHAR
)TextVideoBuffer
;
302 for (i
=X
, j
=0; Text
[j
] && i
<UiScreenWidth
; i
++,j
++)
304 ScreenMemory
[((Y
*2)*UiScreenWidth
)+(i
*2)] = (UCHAR
)Text
[j
];
305 ScreenMemory
[((Y
*2)*UiScreenWidth
)+(i
*2)+1] = Attr
;
309 VOID
TuiDrawCenteredText(ULONG Left
, ULONG Top
, ULONG Right
, ULONG Bottom
, PCSTR TextString
, UCHAR Attr
)
314 ULONG LineBreakCount
;
323 TextLength
= strlen(TextString
);
325 // Count the new lines and the box width
329 for (Index
=0; Index
<TextLength
; Index
++)
331 if (TextString
[Index
] == '\n')
338 if ((Index
- LastIndex
) > BoxWidth
)
340 BoxWidth
= (Index
- LastIndex
);
345 BoxHeight
= LineBreakCount
+ 1;
347 RealLeft
= (((Right
- Left
) - BoxWidth
) / 2) + Left
;
348 RealTop
= (((Bottom
- Top
) - BoxHeight
) / 2) + Top
;
351 for (Index
=0; Index
<TextLength
; Index
++)
353 if (TextString
[Index
] == '\n')
360 X
= RealLeft
+ LastIndex
;
363 Temp
[0] = TextString
[Index
];
365 TuiDrawText(X
, Y
, Temp
, Attr
);
370 VOID
TuiDrawStatusText(PCSTR StatusText
)
374 TuiDrawText(0, UiScreenHeight
-1, " ", ATTR(UiStatusBarFgColor
, UiStatusBarBgColor
));
375 TuiDrawText(1, UiScreenHeight
-1, StatusText
, ATTR(UiStatusBarFgColor
, UiStatusBarBgColor
));
377 for (i
=strlen(StatusText
)+1; i
<UiScreenWidth
; i
++)
379 TuiDrawText(i
, UiScreenHeight
-1, " ", ATTR(UiStatusBarFgColor
, UiStatusBarBgColor
));
382 VideoCopyOffScreenBufferToVRAM();
385 VOID
TuiUpdateDateTime(VOID
)
387 ULONG Year
, Month
, Day
;
388 ULONG Hour
, Minute
, Second
;
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
)
398 /* This happens on QEmu sometimes. We just skip updating */
401 // Get the month name
402 strcpy(DateString
, UiMonthNames
[Month
- 1]);
404 itoa(Day
, TempString
, 10);
405 // Get the day postfix
406 if (1 == Day
|| 21 == Day
|| 31 == Day
)
408 strcat(TempString
, "st");
410 else if (2 == Day
|| 22 == Day
)
412 strcat(TempString
, "nd");
414 else if (3 == Day
|| 23 == Day
)
416 strcat(TempString
, "rd");
420 strcat(TempString
, "th");
423 // Add the day to the date
424 strcat(DateString
, TempString
);
425 strcat(DateString
, " ");
427 // Get the year and add it to the date
428 itoa(Year
, TempString
, 10);
429 strcat(DateString
, TempString
);
432 TuiDrawText(UiScreenWidth
-strlen(DateString
)-2, 1, DateString
, ATTR(UiTitleBoxFgColor
, UiTitleBoxBgColor
));
434 // Get the hour and change from 24-hour mode to 12-hour
444 itoa(Hour
, TempString
, 10);
445 strcpy(TimeString
, " ");
446 strcat(TimeString
, TempString
);
447 strcat(TimeString
, ":");
448 itoa(Minute
, TempString
, 10);
451 strcat(TimeString
, "0");
453 strcat(TimeString
, TempString
);
454 strcat(TimeString
, ":");
455 itoa(Second
, TempString
, 10);
458 strcat(TimeString
, "0");
460 strcat(TimeString
, TempString
);
463 strcat(TimeString
, " PM");
467 strcat(TimeString
, " AM");
471 TuiDrawText(UiScreenWidth
-strlen(TimeString
)-2, 2, TimeString
, ATTR(UiTitleBoxFgColor
, UiTitleBoxBgColor
));
474 VOID
TuiSaveScreen(PUCHAR Buffer
)
476 PUCHAR ScreenMemory
= (PUCHAR
)TextVideoBuffer
;
479 for (i
=0; i
< (UiScreenWidth
* UiScreenHeight
* 2); i
++)
481 Buffer
[i
] = ScreenMemory
[i
];
485 VOID
TuiRestoreScreen(PUCHAR Buffer
)
487 PUCHAR ScreenMemory
= (PUCHAR
)TextVideoBuffer
;
490 for (i
=0; i
< (UiScreenWidth
* UiScreenHeight
* 2); i
++)
492 ScreenMemory
[i
] = Buffer
[i
];
496 VOID
TuiMessageBox(PCSTR MessageText
)
500 // Save the screen contents
501 ScreenBuffer
= MmAllocateMemory(UiScreenWidth
* UiScreenHeight
* 2);
502 TuiSaveScreen(ScreenBuffer
);
504 // Display the message box
505 TuiMessageBoxCritical(MessageText
);
507 // Restore the screen contents
508 TuiRestoreScreen(ScreenBuffer
);
509 MmFreeMemory(ScreenBuffer
);
512 VOID
TuiMessageBoxCritical(PCSTR MessageText
)
515 unsigned int height
= 1;
524 for (i
=0; i
<strlen(MessageText
); i
++)
526 if (MessageText
[i
] == '\n')
531 for (i
=0,j
=0,k
=0; i
<height
; i
++)
533 while ((MessageText
[j
] != '\n') && (MessageText
[j
] != 0))
546 // Calculate box area
547 x1
= (UiScreenWidth
- (width
+2))/2;
549 y1
= ((UiScreenHeight
- height
- 2)/2) + 1;
550 y2
= y1
+ height
+ 4;
553 TuiDrawBox(x1
, y1
, x2
, y2
, D_VERT
, D_HORZ
, TRUE
, TRUE
, ATTR(UiMessageBoxFgColor
, UiMessageBoxBgColor
));
556 for (i
=0,j
=0; i
<strlen(MessageText
)+1; i
++)
558 if ((MessageText
[i
] == '\n') || (MessageText
[i
] == 0))
562 UiDrawText(x1
+2, y1
+1+curline
, temp
, ATTR(UiMessageBoxFgColor
, UiMessageBoxBgColor
));
566 temp
[j
++] = MessageText
[i
];
570 strcpy(temp
, " OK ");
571 UiDrawText(x1
+((x2
-x1
)/2)-3, y2
-2, temp
, ATTR(COLOR_BLACK
, COLOR_GRAY
));
574 UiDrawStatusText("Press ENTER to continue");
576 VideoCopyOffScreenBufferToVRAM();
582 key
= MachConsGetCh();
583 if(key
== KEY_EXTENDED
)
584 key
= MachConsGetCh();
588 else if(key
== KEY_SPACE
)
590 else if(key
== KEY_ESC
)
596 VideoCopyOffScreenBufferToVRAM();
602 VOID
TuiDrawProgressBarCenter(ULONG Position
, ULONG Range
, PCHAR ProgressText
)
604 ULONG Left
, Top
, Right
, Bottom
;
605 ULONG Width
= 50; // Allow for 50 "bars"
608 Left
= (UiScreenWidth
- Width
- 4) / 2;
609 Right
= Left
+ Width
+ 3;
610 Top
= (UiScreenHeight
- Height
- 2) / 2;
612 Bottom
= Top
+ Height
+ 1;
614 TuiDrawProgressBar(Left
, Top
, Right
, Bottom
, Position
, Range
, ProgressText
);
617 VOID
TuiDrawProgressBar(ULONG Left
, ULONG Top
, ULONG Right
, ULONG Bottom
, ULONG Position
, ULONG Range
, PCHAR ProgressText
)
620 ULONG ProgressBarWidth
= (Right
- Left
) - 3;
622 // First make sure the progress bar text fits
623 UiTruncateStringEllipsis(ProgressText
, ProgressBarWidth
- 4);
625 if (Position
> Range
)
631 TuiDrawBox(Left
, Top
, Right
, Bottom
, VERT
, HORZ
, TRUE
, TRUE
, ATTR(UiMenuFgColor
, UiMenuBgColor
));
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
));
637 // Draw the percent complete
638 for (i
=0; i
<(Position
*ProgressBarWidth
)/Range
; i
++)
640 TuiDrawText(Left
+2+i
, Top
+2, "\xDB", ATTR(UiTextColor
, UiMenuBgColor
));
644 for (; i
<ProgressBarWidth
; i
++)
646 TuiDrawText(Left
+2+i
, Top
+2, "\xB2", ATTR(UiTextColor
, UiMenuBgColor
));
651 VideoCopyOffScreenBufferToVRAM();
654 UCHAR
TuiTextToColor(PCSTR ColorText
)
656 if (stricmp(ColorText
, "Black") == 0)
658 else if (stricmp(ColorText
, "Blue") == 0)
660 else if (stricmp(ColorText
, "Green") == 0)
662 else if (stricmp(ColorText
, "Cyan") == 0)
664 else if (stricmp(ColorText
, "Red") == 0)
666 else if (stricmp(ColorText
, "Magenta") == 0)
667 return COLOR_MAGENTA
;
668 else if (stricmp(ColorText
, "Brown") == 0)
670 else if (stricmp(ColorText
, "Gray") == 0)
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)
686 else if (stricmp(ColorText
, "White") == 0)
692 UCHAR
TuiTextToFillStyle(PCSTR FillStyleText
)
694 if (stricmp(FillStyleText
, "Light") == 0)
698 else if (stricmp(FillStyleText
, "Medium") == 0)
702 else if (stricmp(FillStyleText
, "Dark") == 0)
710 VOID
TuiFadeInBackdrop(VOID
)
712 PPALETTE_ENTRY TuiFadePalette
= NULL
;
714 if (UiUseSpecialEffects
&& ! MachVideoIsPaletteFixed())
716 TuiFadePalette
= (PPALETTE_ENTRY
)MmAllocateMemory(sizeof(PALETTE_ENTRY
) * 64);
718 if (TuiFadePalette
!= NULL
)
720 VideoSavePaletteState(TuiFadePalette
, 64);
721 VideoSetAllColorsToBlack(64);
725 // Draw the backdrop and title box
728 if (UiUseSpecialEffects
&& ! MachVideoIsPaletteFixed() && TuiFadePalette
!= NULL
)
730 VideoFadeIn(TuiFadePalette
, 64);
731 MmFreeMemory(TuiFadePalette
);
735 VOID
TuiFadeOut(VOID
)
737 PPALETTE_ENTRY TuiFadePalette
= NULL
;
739 if (UiUseSpecialEffects
&& ! MachVideoIsPaletteFixed())
741 TuiFadePalette
= (PPALETTE_ENTRY
)MmAllocateMemory(sizeof(PALETTE_ENTRY
) * 64);
743 if (TuiFadePalette
!= NULL
)
745 VideoSavePaletteState(TuiFadePalette
, 64);
749 if (UiUseSpecialEffects
&& ! MachVideoIsPaletteFixed() && TuiFadePalette
!= NULL
)
754 MachVideoSetDisplayMode(NULL
, FALSE
);
756 if (UiUseSpecialEffects
&& ! MachVideoIsPaletteFixed() && TuiFadePalette
!= NULL
)
758 VideoRestorePaletteState(TuiFadePalette
, 64);
759 MmFreeMemory(TuiFadePalette
);
764 BOOL
TuiEditBox(PCSTR MessageText
, PCHAR EditTextBuffer
, ULONG Length
)
767 unsigned int height
= 1;
775 ULONG EditBoxStartX
, EditBoxEndX
;
777 unsigned int EditBoxTextCount
;
778 int EditBoxTextDisplayIndex
;
782 // Save the screen contents
783 ScreenBuffer
= MmAllocateMemory(UiScreenWidth
* UiScreenHeight
* 2);
784 TuiSaveScreen(ScreenBuffer
);
787 for (i
=0; i
<strlen(MessageText
); i
++)
789 if (MessageText
[i
] == '\n')
794 for (i
=0,j
=0,k
=0; i
<height
; i
++)
796 while ((MessageText
[j
] != '\n') && (MessageText
[j
] != 0))
809 // Calculate box area
810 x1
= (UiScreenWidth
- (width
+2))/2;
812 y1
= ((UiScreenHeight
- height
- 2)/2) + 1;
813 y2
= y1
+ height
+ 4;
816 TuiDrawBox(x1
, y1
, x2
, y2
, D_VERT
, D_HORZ
, TRUE
, TRUE
, ATTR(UiMessageBoxFgColor
, UiMessageBoxBgColor
));
819 for (i
=0,j
=0; i
<strlen(MessageText
)+1; i
++)
821 if ((MessageText
[i
] == '\n') || (MessageText
[i
] == 0))
825 UiDrawText(x1
+2, y1
+1+curline
, temp
, ATTR(UiMessageBoxFgColor
, UiMessageBoxBgColor
));
829 temp
[j
++] = MessageText
[i
];
832 EditBoxTextCount
= 0;
833 EditBoxLine
= y2
- 2;
834 EditBoxStartX
= x1
+ 3;
835 EditBoxEndX
= x2
- 3;
836 UiFillArea(EditBoxStartX
, EditBoxLine
, EditBoxEndX
, EditBoxLine
, ' ', ATTR(UiEditBoxTextColor
, UiEditBoxBgColor
));
839 EditBoxCursorX
= EditBoxStartX
;
840 MachVideoSetTextCursorPosition(EditBoxCursorX
, EditBoxLine
);
841 MachVideoHideShowTextCursor(TRUE
);
844 UiDrawStatusText("Press ENTER to continue, or ESC to cancel");
846 VideoCopyOffScreenBufferToVRAM();
852 key
= MachConsGetCh();
853 if(key
== KEY_EXTENDED
)
855 key
= MachConsGetCh();
863 else if(key
== KEY_ESC
)
868 else if (key
== KEY_BACKSPACE
) // Remove a character
870 if (EditBoxTextCount
)
873 EditTextBuffer
[EditBoxTextCount
] = 0;
880 else // Add this key to the buffer
882 if (EditBoxTextCount
< Length
- 1)
884 EditTextBuffer
[EditBoxTextCount
] = key
;
886 EditTextBuffer
[EditBoxTextCount
] = 0;
895 // Draw the edit box background
896 UiFillArea(EditBoxStartX
, EditBoxLine
, EditBoxEndX
, EditBoxLine
, ' ', ATTR(UiEditBoxTextColor
, UiEditBoxBgColor
));
899 if (EditBoxTextCount
> (EditBoxEndX
- EditBoxStartX
))
901 EditBoxTextDisplayIndex
= EditBoxTextCount
- (EditBoxEndX
- EditBoxStartX
);
902 EditBoxCursorX
= EditBoxEndX
;
906 EditBoxTextDisplayIndex
= 0;
907 EditBoxCursorX
= EditBoxStartX
+ EditBoxTextCount
;
909 UiDrawText(EditBoxStartX
, EditBoxLine
, &EditTextBuffer
[EditBoxTextDisplayIndex
], ATTR(UiEditBoxTextColor
, UiEditBoxBgColor
));
912 MachVideoSetTextCursorPosition(EditBoxCursorX
, EditBoxLine
);
916 VideoCopyOffScreenBufferToVRAM();
919 // Hide the cursor again
920 MachVideoHideShowTextCursor(FALSE
);
922 // Restore the screen contents
923 TuiRestoreScreen(ScreenBuffer
);
924 MmFreeMemory(ScreenBuffer
);