mirror of
https://github.com/reactos/reactos.git
synced 2025-05-31 23:18:39 +00:00

- Added protected mode exception handling in case FreeLoader crashes - Reworked memory manager to use all of extended memory - Reworked UI code, now supports multiple text-mode resolutions svn path=/trunk/; revision=3010
608 lines
13 KiB
C
608 lines
13 KiB
C
/*
|
|
* FreeLoader
|
|
* Copyright (C) 1998-2002 Brian Palmer <brianp@sginet.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
*/
|
|
|
|
#include <freeldr.h>
|
|
#include <ui.h>
|
|
#include "tui.h"
|
|
#include "keycodes.h"
|
|
#include <rtl.h>
|
|
#include <mm.h>
|
|
#include <debug.h>
|
|
#include <inifile.h>
|
|
#include <version.h>
|
|
|
|
VOID TuiDrawBackdrop(VOID)
|
|
{
|
|
//
|
|
// Fill in the background (excluding title box & status bar)
|
|
//
|
|
TuiFillArea(0,
|
|
TUI_TITLE_BOX_CHAR_HEIGHT,
|
|
UiScreenWidth - 1,
|
|
UiScreenHeight - 2,
|
|
UiBackdropFillStyle,
|
|
ATTR(UiBackdropFgColor, UiBackdropBgColor));
|
|
|
|
//
|
|
// Draw the title box
|
|
//
|
|
TuiDrawBox(0,
|
|
0,
|
|
UiScreenWidth - 1,
|
|
TUI_TITLE_BOX_CHAR_HEIGHT - 1,
|
|
D_VERT,
|
|
D_HORZ,
|
|
TRUE,
|
|
FALSE,
|
|
ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
|
|
|
|
//
|
|
// Draw version text
|
|
//
|
|
TuiDrawText(2,
|
|
1,
|
|
GetFreeLoaderVersionString(),
|
|
ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
|
|
|
|
//
|
|
// Draw copyright
|
|
//
|
|
TuiDrawText(2,
|
|
2,
|
|
BY_AUTHOR,
|
|
ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
|
|
TuiDrawText(2,
|
|
3,
|
|
AUTHOR_EMAIL,
|
|
ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
|
|
|
|
//
|
|
// Draw help text
|
|
//
|
|
//TuiDrawText(UiScreenWidth - 16, 3, /*"F1 for Help"*/"F8 for Options", ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
|
|
|
|
//
|
|
// Draw title text
|
|
//
|
|
TuiDrawText( (UiScreenWidth / 2) - (strlen(UiTitleBoxTitleText) / 2),
|
|
2,
|
|
UiTitleBoxTitleText,
|
|
ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
|
|
|
|
//
|
|
// Draw status bar
|
|
//
|
|
TuiDrawStatusText("");
|
|
|
|
//
|
|
// Update the date & time
|
|
//
|
|
TuiUpdateDateTime();
|
|
}
|
|
|
|
/*
|
|
* FillArea()
|
|
* This function assumes coordinates are zero-based
|
|
*/
|
|
VOID TuiFillArea(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR FillChar, UCHAR Attr /* Color Attributes */)
|
|
{
|
|
PUCHAR ScreenMemory = (PUCHAR)TUI_SCREEN_MEM;
|
|
ULONG i, j;
|
|
|
|
// Clip the area to the screen
|
|
// FIXME: This code seems to have problems... Uncomment and view ;-)
|
|
/*if ((Left >= UiScreenWidth) || (Top >= UiScreenHeight))
|
|
{
|
|
return;
|
|
}
|
|
if ((Left + Right) >= UiScreenWidth)
|
|
{
|
|
Right = UiScreenWidth - Left;
|
|
}
|
|
if ((Top + Bottom) >= UiScreenHeight)
|
|
{
|
|
Bottom = UiScreenHeight - Top;
|
|
}*/
|
|
|
|
// Loop through each line and fill it in
|
|
for (i=Top; i<=Bottom; i++)
|
|
{
|
|
// Loop through each character (column) in the line and fill it in
|
|
for (j=Left; j<=Right; j++)
|
|
{
|
|
ScreenMemory[((i*2)*UiScreenWidth)+(j*2)] = FillChar;
|
|
ScreenMemory[((i*2)*UiScreenWidth)+(j*2)+1] = Attr;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* DrawShadow()
|
|
* This function assumes coordinates are zero-based
|
|
*/
|
|
VOID TuiDrawShadow(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom)
|
|
{
|
|
PUCHAR ScreenMemory = (PUCHAR)TUI_SCREEN_MEM;
|
|
ULONG Idx;
|
|
|
|
// Shade the bottom of the area
|
|
if (Bottom < (UiScreenHeight - 1))
|
|
{
|
|
if (UiScreenHeight < 34)
|
|
{
|
|
Idx=Left + 2;
|
|
}
|
|
else
|
|
{
|
|
Idx=Left + 1;
|
|
}
|
|
|
|
for (; Idx<=Right; Idx++)
|
|
{
|
|
ScreenMemory[(((Bottom+1)*2)*UiScreenWidth)+(Idx*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
|
|
}
|
|
}
|
|
|
|
// Shade the right of the area
|
|
if (Right < (UiScreenWidth - 1))
|
|
{
|
|
for (Idx=Top+1; Idx<=Bottom; Idx++)
|
|
{
|
|
ScreenMemory[((Idx*2)*UiScreenWidth)+((Right+1)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
|
|
}
|
|
}
|
|
if (UiScreenHeight < 34)
|
|
{
|
|
if ((Right + 1) < (UiScreenWidth - 1))
|
|
{
|
|
for (Idx=Top+1; Idx<=Bottom; Idx++)
|
|
{
|
|
ScreenMemory[((Idx*2)*UiScreenWidth)+((Right+2)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Shade the bottom right corner
|
|
if ((Right < (UiScreenWidth - 1)) && (Bottom < (UiScreenHeight - 1)))
|
|
{
|
|
ScreenMemory[(((Bottom+1)*2)*UiScreenWidth)+((Right+1)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
|
|
}
|
|
if (UiScreenHeight < 34)
|
|
{
|
|
if (((Right + 1) < (UiScreenWidth - 1)) && (Bottom < (UiScreenHeight - 1)))
|
|
{
|
|
ScreenMemory[(((Bottom+1)*2)*UiScreenWidth)+((Right+2)*2)+1] = ATTR(COLOR_GRAY, COLOR_BLACK);
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* DrawBox()
|
|
* This function assumes coordinates are zero-based
|
|
*/
|
|
VOID TuiDrawBox(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, UCHAR VertStyle, UCHAR HorzStyle, BOOL Fill, BOOL Shadow, UCHAR Attr)
|
|
{
|
|
UCHAR ULCorner, URCorner, LLCorner, LRCorner;
|
|
|
|
// Calculate the corner values
|
|
if (HorzStyle == HORZ)
|
|
{
|
|
if (VertStyle == VERT)
|
|
{
|
|
ULCorner = UL;
|
|
URCorner = UR;
|
|
LLCorner = LL;
|
|
LRCorner = LR;
|
|
}
|
|
else // VertStyle == D_VERT
|
|
{
|
|
ULCorner = VD_UL;
|
|
URCorner = VD_UR;
|
|
LLCorner = VD_LL;
|
|
LRCorner = VD_LR;
|
|
}
|
|
}
|
|
else // HorzStyle == D_HORZ
|
|
{
|
|
if (VertStyle == VERT)
|
|
{
|
|
ULCorner = HD_UL;
|
|
URCorner = HD_UR;
|
|
LLCorner = HD_LL;
|
|
LRCorner = HD_LR;
|
|
}
|
|
else // VertStyle == D_VERT
|
|
{
|
|
ULCorner = D_UL;
|
|
URCorner = D_UR;
|
|
LLCorner = D_LL;
|
|
LRCorner = D_LR;
|
|
}
|
|
}
|
|
|
|
// Fill in box background
|
|
if (Fill)
|
|
{
|
|
TuiFillArea(Left, Top, Right, Bottom, ' ', Attr);
|
|
}
|
|
|
|
// Fill in corners
|
|
TuiFillArea(Left, Top, Left, Top, ULCorner, Attr);
|
|
TuiFillArea(Right, Top, Right, Top, URCorner, Attr);
|
|
TuiFillArea(Left, Bottom, Left, Bottom, LLCorner, Attr);
|
|
TuiFillArea(Right, Bottom, Right, Bottom, LRCorner, Attr);
|
|
|
|
// Fill in left line
|
|
TuiFillArea(Left, Top+1, Left, Bottom-1, VertStyle, Attr);
|
|
// Fill in top line
|
|
TuiFillArea(Left+1, Top, Right-1, Top, HorzStyle, Attr);
|
|
// Fill in right line
|
|
TuiFillArea(Right, Top+1, Right, Bottom-1, VertStyle, Attr);
|
|
// Fill in bottom line
|
|
TuiFillArea(Left+1, Bottom, Right-1, Bottom, HorzStyle, Attr);
|
|
|
|
// Draw the shadow
|
|
if (Shadow)
|
|
{
|
|
TuiDrawShadow(Left, Top, Right, Bottom);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* DrawText()
|
|
* This function assumes coordinates are zero-based
|
|
*/
|
|
VOID TuiDrawText(ULONG X, ULONG Y, PUCHAR Text, UCHAR Attr)
|
|
{
|
|
PUCHAR ScreenMemory = (PUCHAR)TUI_SCREEN_MEM;
|
|
ULONG i, j;
|
|
|
|
// Draw the text
|
|
for (i=X, j=0; Text[j] && i<UiScreenWidth; i++,j++)
|
|
{
|
|
ScreenMemory[((Y*2)*UiScreenWidth)+(i*2)] = Text[j];
|
|
ScreenMemory[((Y*2)*UiScreenWidth)+(i*2)+1] = Attr;
|
|
}
|
|
}
|
|
|
|
VOID TuiDrawCenteredText(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, PUCHAR TextString, UCHAR Attr)
|
|
{
|
|
}
|
|
|
|
VOID TuiDrawStatusText(PUCHAR StatusText)
|
|
{
|
|
ULONG i;
|
|
|
|
TuiDrawText(0, UiScreenHeight-1, " ", ATTR(UiStatusBarFgColor, UiStatusBarBgColor));
|
|
TuiDrawText(1, UiScreenHeight-1, StatusText, ATTR(UiStatusBarFgColor, UiStatusBarBgColor));
|
|
|
|
for (i=strlen(StatusText)+1; i<UiScreenWidth; i++)
|
|
{
|
|
TuiDrawText(i, UiScreenHeight-1, " ", ATTR(UiStatusBarFgColor, UiStatusBarBgColor));
|
|
}
|
|
}
|
|
|
|
VOID TuiUpdateDateTime(VOID)
|
|
{
|
|
UCHAR DateString[40];
|
|
UCHAR TimeString[40];
|
|
UCHAR TempString[20];
|
|
ULONG Hour, Minute, Second;
|
|
BOOL PMHour = FALSE;
|
|
|
|
// Get the month name
|
|
strcpy(DateString, UiMonthNames[getmonth()-1]);
|
|
// Get the day
|
|
itoa(getday(), TempString, 10);
|
|
// Get the day postfix
|
|
if ((getday() == 1) || (getday() == 21) || (getday() == 31))
|
|
{
|
|
strcat(TempString, "st");
|
|
}
|
|
else if ((getday() == 2) || (getday() == 22))
|
|
{
|
|
strcat(TempString, "nd");
|
|
}
|
|
else if ((getday() == 3) || (getday() == 23))
|
|
{
|
|
strcat(TempString, "rd");
|
|
}
|
|
else
|
|
{
|
|
strcat(TempString, "th");
|
|
}
|
|
|
|
// Add the day to the date
|
|
strcat(DateString, TempString);
|
|
strcat(DateString, " ");
|
|
|
|
// Get the year and add it to the date
|
|
itoa(getyear(), TempString, 10);
|
|
strcat(DateString, TempString);
|
|
|
|
// Draw the date
|
|
TuiDrawText(UiScreenWidth-strlen(DateString)-2, 1, DateString, ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
|
|
|
|
// Get the hour and change from 24-hour mode to 12-hour
|
|
Hour = gethour();
|
|
if (Hour > 12)
|
|
{
|
|
Hour -= 12;
|
|
PMHour = TRUE;
|
|
}
|
|
if (Hour == 0)
|
|
{
|
|
Hour = 12;
|
|
}
|
|
Minute = getminute();
|
|
Second = getsecond();
|
|
itoa(Hour, TempString, 10);
|
|
strcpy(TimeString, " ");
|
|
strcat(TimeString, TempString);
|
|
strcat(TimeString, ":");
|
|
itoa(Minute, TempString, 10);
|
|
if (Minute < 10)
|
|
{
|
|
strcat(TimeString, "0");
|
|
}
|
|
strcat(TimeString, TempString);
|
|
strcat(TimeString, ":");
|
|
itoa(Second, TempString, 10);
|
|
if (Second < 10)
|
|
{
|
|
strcat(TimeString, "0");
|
|
}
|
|
strcat(TimeString, TempString);
|
|
if (PMHour)
|
|
{
|
|
strcat(TimeString, " PM");
|
|
}
|
|
else
|
|
{
|
|
strcat(TimeString, " AM");
|
|
}
|
|
|
|
// Draw the time
|
|
TuiDrawText(UiScreenWidth-strlen(TimeString)-2, 2, TimeString, ATTR(UiTitleBoxFgColor, UiTitleBoxBgColor));
|
|
}
|
|
|
|
VOID TuiSaveScreen(PUCHAR Buffer)
|
|
{
|
|
PUCHAR ScreenMemory = (PUCHAR)TUI_SCREEN_MEM;
|
|
ULONG i;
|
|
|
|
for (i=0; i < (UiScreenWidth * UiScreenHeight * 2); i++)
|
|
{
|
|
Buffer[i] = ScreenMemory[i];
|
|
}
|
|
}
|
|
|
|
VOID TuiRestoreScreen(PUCHAR Buffer)
|
|
{
|
|
PUCHAR ScreenMemory = (PUCHAR)TUI_SCREEN_MEM;
|
|
ULONG i;
|
|
|
|
for (i=0; i < (UiScreenWidth * UiScreenHeight * 2); i++)
|
|
{
|
|
ScreenMemory[i] = Buffer[i];
|
|
}
|
|
}
|
|
|
|
VOID TuiMessageBox(PUCHAR MessageText)
|
|
{
|
|
PVOID ScreenBuffer;
|
|
|
|
// Save the screen contents
|
|
ScreenBuffer = MmAllocateMemory(UiScreenWidth * UiScreenHeight * 2);
|
|
TuiSaveScreen(ScreenBuffer);
|
|
|
|
// Display the message box
|
|
TuiMessageBoxCritical(MessageText);
|
|
|
|
// Restore the screen contents
|
|
TuiRestoreScreen(ScreenBuffer);
|
|
MmFreeMemory(ScreenBuffer);
|
|
}
|
|
|
|
VOID TuiMessageBoxCritical(PUCHAR MessageText)
|
|
{
|
|
int width = 8;
|
|
int height = 1;
|
|
int curline = 0;
|
|
int i , j, k;
|
|
int x1, x2, y1, y2;
|
|
char temp[260];
|
|
char key;
|
|
|
|
// Find the height
|
|
for (i=0; i<strlen(MessageText); i++)
|
|
{
|
|
if (MessageText[i] == '\n')
|
|
height++;
|
|
}
|
|
|
|
// Find the width
|
|
for (i=0,j=0,k=0; i<height; i++)
|
|
{
|
|
while ((MessageText[j] != '\n') && (MessageText[j] != 0))
|
|
{
|
|
j++;
|
|
k++;
|
|
}
|
|
|
|
if (k > width)
|
|
width = k;
|
|
|
|
k = 0;
|
|
j++;
|
|
}
|
|
|
|
// Calculate box area
|
|
x1 = (UiScreenWidth - (width+2))/2;
|
|
x2 = x1 + width + 3;
|
|
y1 = ((UiScreenHeight - height - 2)/2) + 1;
|
|
y2 = y1 + height + 4;
|
|
|
|
// Draw the box
|
|
TuiDrawBox(x1, y1, x2, y2, D_VERT, D_HORZ, TRUE, TRUE, ATTR(UiMessageBoxFgColor, UiMessageBoxBgColor));
|
|
|
|
// Draw the text
|
|
for (i=0,j=0; i<strlen(MessageText)+1; i++)
|
|
{
|
|
if ((MessageText[i] == '\n') || (MessageText[i] == 0))
|
|
{
|
|
temp[j] = 0;
|
|
j = 0;
|
|
UiDrawText(x1+2, y1+1+curline, temp, ATTR(UiMessageBoxFgColor, UiMessageBoxBgColor));
|
|
curline++;
|
|
}
|
|
else
|
|
temp[j++] = MessageText[i];
|
|
}
|
|
|
|
// Draw OK button
|
|
strcpy(temp, " OK ");
|
|
UiDrawText(x1+((x2-x1)/2)-3, y2-2, temp, ATTR(COLOR_BLACK, COLOR_GRAY));
|
|
|
|
// Draw status text
|
|
UiDrawStatusText("Press ENTER to continue");
|
|
|
|
for (;;)
|
|
{
|
|
if (kbhit())
|
|
{
|
|
key = getch();
|
|
if(key == KEY_EXTENDED)
|
|
key = getch();
|
|
|
|
if(key == KEY_ENTER)
|
|
break;
|
|
else if(key == KEY_SPACE)
|
|
break;
|
|
else if(key == KEY_ESC)
|
|
break;
|
|
}
|
|
|
|
TuiUpdateDateTime();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
VOID TuiDrawProgressBarCenter(ULONG Position, ULONG Range)
|
|
{
|
|
ULONG Left, Top, Right, Bottom;
|
|
ULONG Width = 50; // Allow for 50 "bars"
|
|
ULONG Height = 2;
|
|
|
|
Left = (UiScreenWidth - Width - 4) / 2;
|
|
Right = Left + Width + 3;
|
|
Top = (UiScreenHeight - Height - 2) / 2;
|
|
Top += 2;
|
|
Bottom = Top + Height + 1;
|
|
|
|
TuiDrawProgressBar(Left, Top, Right, Bottom, Position, Range);
|
|
}
|
|
|
|
VOID TuiDrawProgressBar(ULONG Left, ULONG Top, ULONG Right, ULONG Bottom, ULONG Position, ULONG Range)
|
|
{
|
|
ULONG i;
|
|
ULONG ProgressBarWidth = (Right - Left) - 3;
|
|
|
|
if (Position > Range)
|
|
{
|
|
Position = Range;
|
|
}
|
|
|
|
// Draw the box
|
|
TuiDrawBox(Left, Top, Right, Bottom, VERT, HORZ, TRUE, TRUE, ATTR(UiMenuFgColor, UiMenuBgColor));
|
|
|
|
// Draw the "Loading..." text
|
|
TuiDrawText(70/2, Top+1, "Loading...", ATTR(UiTextColor, UiMenuBgColor));
|
|
|
|
// Draw the percent complete
|
|
for (i=0; i<(Position*ProgressBarWidth)/Range; i++)
|
|
{
|
|
TuiDrawText(Left+2+i, Top+2, "\xDB", ATTR(UiTextColor, UiMenuBgColor));
|
|
}
|
|
|
|
// Draw the rest
|
|
for (; i<ProgressBarWidth; i++)
|
|
{
|
|
TuiDrawText(Left+2+i, Top+2, "\xB2", ATTR(UiTextColor, UiMenuBgColor));
|
|
}
|
|
|
|
TuiUpdateDateTime();
|
|
}
|
|
|
|
UCHAR TuiTextToColor(PUCHAR ColorText)
|
|
{
|
|
if (stricmp(ColorText, "Black") == 0)
|
|
return COLOR_BLACK;
|
|
else if (stricmp(ColorText, "Blue") == 0)
|
|
return COLOR_BLUE;
|
|
else if (stricmp(ColorText, "Green") == 0)
|
|
return COLOR_GREEN;
|
|
else if (stricmp(ColorText, "Cyan") == 0)
|
|
return COLOR_CYAN;
|
|
else if (stricmp(ColorText, "Red") == 0)
|
|
return COLOR_RED;
|
|
else if (stricmp(ColorText, "Magenta") == 0)
|
|
return COLOR_MAGENTA;
|
|
else if (stricmp(ColorText, "Brown") == 0)
|
|
return COLOR_BROWN;
|
|
else if (stricmp(ColorText, "Gray") == 0)
|
|
return COLOR_GRAY;
|
|
else if (stricmp(ColorText, "DarkGray") == 0)
|
|
return COLOR_DARKGRAY;
|
|
else if (stricmp(ColorText, "LightBlue") == 0)
|
|
return COLOR_LIGHTBLUE;
|
|
else if (stricmp(ColorText, "LightGreen") == 0)
|
|
return COLOR_LIGHTGREEN;
|
|
else if (stricmp(ColorText, "LightCyan") == 0)
|
|
return COLOR_LIGHTCYAN;
|
|
else if (stricmp(ColorText, "LightRed") == 0)
|
|
return COLOR_LIGHTRED;
|
|
else if (stricmp(ColorText, "LightMagenta") == 0)
|
|
return COLOR_LIGHTMAGENTA;
|
|
else if (stricmp(ColorText, "Yellow") == 0)
|
|
return COLOR_YELLOW;
|
|
else if (stricmp(ColorText, "White") == 0)
|
|
return COLOR_WHITE;
|
|
|
|
return COLOR_BLACK;
|
|
}
|
|
|
|
UCHAR TuiTextToFillStyle(PUCHAR FillStyleText)
|
|
{
|
|
if (stricmp(FillStyleText, "Light") == 0)
|
|
{
|
|
return LIGHT_FILL;
|
|
}
|
|
else if (stricmp(FillStyleText, "Medium") == 0)
|
|
{
|
|
return MEDIUM_FILL;
|
|
}
|
|
else if (stricmp(FillStyleText, "Dark") == 0)
|
|
{
|
|
return DARK_FILL;
|
|
}
|
|
|
|
return LIGHT_FILL;
|
|
}
|