TuiPrintf(const char *Format,
...)
{
- int i;
- int Length;
- va_list ap;
- CHAR Buffer[512];
+ int i;
+ int Length;
+ va_list ap;
+ CHAR Buffer[512];
- va_start(ap, Format);
- Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap);
- va_end(ap);
+ va_start(ap, Format);
+ Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap);
+ va_end(ap);
- if (Length == -1) Length = sizeof(Buffer);
+ if (Length == -1) Length = sizeof(Buffer);
- for (i = 0; i < Length; i++)
- {
- MachConsPutChar(Buffer[i]);
- }
+ for (i = 0; i < Length; i++)
+ {
+ MachConsPutChar(Buffer[i]);
+ }
- return Length;
+ return Length;
}
BOOLEAN
UiInitialize(IN BOOLEAN ShowGui)
{
- ULONG Depth;
-
+ ULONG Depth;
+
/* Nothing to do */
if (!ShowGui) return TRUE;
/* Set mode and query size */
- MachVideoSetDisplayMode(NULL, TRUE);
- MachVideoGetDisplaySize(&UiScreenWidth, &UiScreenHeight, &Depth);
- return TRUE;
+ MachVideoSetDisplayMode(NULL, TRUE);
+ MachVideoGetDisplaySize(&UiScreenWidth, &UiScreenHeight, &Depth);
+ return TRUE;
}
VOID
VOID
UiDrawBackdrop(VOID)
{
- /* Clear the screen */
- MachVideoClearScreen(ATTR(COLOR_WHITE, COLOR_BLACK));
+ /* Clear the screen */
+ MachVideoClearScreen(ATTR(COLOR_WHITE, COLOR_BLACK));
}
VOID
IN PCSTR Text,
IN UCHAR Attr)
{
- ULONG i, j;
+ ULONG i, j;
+
+ /* Draw the text character by character, but don't exceed the width */
+ for (i = X, j = 0; Text[j] && i < UiScreenWidth; i++, j++)
+ {
+ /* Write the character */
+ MachVideoPutChar(Text[j], Attr, i, Y);
+ }
+}
+
+VOID
+UiDrawText2(IN ULONG X,
+ IN ULONG Y,
+ IN ULONG MaxNumChars,
+ IN PCSTR Text,
+ IN UCHAR Attr)
+{
+ ULONG i, j;
/* Draw the text character by character, but don't exceed the width */
- for (i = X, j = 0; Text[j] && i < UiScreenWidth; i++, j++)
- {
- /* Write the character */
+ for (i = X, j = 0; Text[j] && i < UiScreenWidth && (MaxNumChars > 0 ? j < MaxNumChars : TRUE); i++, j++)
+ {
+ /* Write the character */
MachVideoPutChar(Text[j], Attr, i, Y);
- }
+ }
}
VOID
IN PCSTR TextString,
IN UCHAR Attr)
{
- ULONG TextLength, BoxWidth, BoxHeight, LineBreakCount, Index, LastIndex;
- ULONG RealLeft, RealTop, X, Y;
- CHAR Temp[2];
+ ULONG TextLength, BoxWidth, BoxHeight, LineBreakCount, Index, LastIndex;
+ ULONG RealLeft, RealTop, X, Y;
+ CHAR Temp[2];
/* Query text length */
- TextLength = strlen(TextString);
+ TextLength = strlen(TextString);
/* Count the new lines and the box width */
- LineBreakCount = 0;
- BoxWidth = 0;
- LastIndex = 0;
- for (Index=0; Index < TextLength; Index++)
- {
- /* Scan for new lines */
- if (TextString[Index] == '\n')
- {
- /* Remember the new line */
- LastIndex = Index;
- LineBreakCount++;
- }
- else
- {
- /* Check for new larger box width */
- if ((Index - LastIndex) > BoxWidth)
- {
- /* Update it */
- BoxWidth = (Index - LastIndex);
- }
- }
- }
+ LineBreakCount = 0;
+ BoxWidth = 0;
+ LastIndex = 0;
+ for (Index=0; Index < TextLength; Index++)
+ {
+ /* Scan for new lines */
+ if (TextString[Index] == '\n')
+ {
+ /* Remember the new line */
+ LastIndex = Index;
+ LineBreakCount++;
+ }
+ else
+ {
+ /* Check for new larger box width */
+ if ((Index - LastIndex) > BoxWidth)
+ {
+ /* Update it */
+ BoxWidth = (Index - LastIndex);
+ }
+ }
+ }
/* Base the box height on the number of lines */
- BoxHeight = LineBreakCount + 1;
+ BoxHeight = LineBreakCount + 1;
/* Create the centered coordinates */
- RealLeft = (((Right - Left) - BoxWidth) / 2) + Left;
- RealTop = (((Bottom - Top) - BoxHeight) / 2) + Top;
+ RealLeft = (((Right - Left) - BoxWidth) / 2) + Left;
+ RealTop = (((Bottom - Top) - BoxHeight) / 2) + Top;
/* Now go for a second scan */
- LastIndex = 0;
- for (Index=0; Index < TextLength; Index++)
- {
- /* Look for new lines again */
- if (TextString[Index] == '\n')
- {
- /* Update where the text should start */
- RealTop++;
- LastIndex = 0;
- }
- else
- {
- /* We've got a line of text to print, do it */
- X = RealLeft + LastIndex;
- Y = RealTop;
- LastIndex++;
- Temp[0] = TextString[Index];
- Temp[1] = 0;
- UiDrawText(X, Y, Temp, Attr);
- }
- }
+ LastIndex = 0;
+ for (Index=0; Index < TextLength; Index++)
+ {
+ /* Look for new lines again */
+ if (TextString[Index] == '\n')
+ {
+ /* Update where the text should start */
+ RealTop++;
+ LastIndex = 0;
+ }
+ else
+ {
+ /* We've got a line of text to print, do it */
+ X = RealLeft + LastIndex;
+ Y = RealTop;
+ LastIndex++;
+ Temp[0] = TextString[Index];
+ Temp[1] = 0;
+ UiDrawText(X, Y, Temp, Attr);
+ }
+ }
}
VOID
{
ULONG Left, Top, Right, Bottom, Width, Height;
- /* Build the coordinates and sizes */
- Height = 2;
- Width = UiScreenWidth;
- Left = 0;
- Right = (Left + Width) - 1;
- Top = UiScreenHeight - Height - 4;
- Bottom = Top + Height + 1;
+ /* Build the coordinates and sizes */
+ Height = 2;
+ Width = UiScreenWidth;
+ Left = 0;
+ Right = (Left + Width) - 1;
+ Top = UiScreenHeight - Height - 4;
+ Bottom = Top + Height + 1;
/* Draw the progress bar */
- UiDrawProgressBar(Left, Top, Right, Bottom, Position, Range, ProgressText);
+ UiDrawProgressBar(Left, Top, Right, Bottom, Position, Range, ProgressText);
}
VOID
UiDrawProgressBar(IN ULONG Left,
IN ULONG Top,
IN ULONG Right,
- IN ULONG Bottom,
+ IN ULONG Bottom,
IN ULONG Position,
IN ULONG Range,
IN PCHAR ProgressText)
{
ULONG i, ProgressBarWidth;
-
- /* Calculate the width of the bar proper */
- ProgressBarWidth = (Right - Left) - 3;
-
- /* First make sure the progress bar text fits */
- UiTruncateStringEllipsis(ProgressText, ProgressBarWidth - 4);
- if (Position > Range) Position = Range;
-
- /* Draw the "Loading..." text */
- UiDrawCenteredText(Left + 2, Top + 1, Right - 2, Top + 1, ProgressText, ATTR(7, 0));
-
- /* Draw the percent complete */
- for (i = 0; i < (Position * ProgressBarWidth) / Range; i++)
- {
- /* Use the fill character */
- UiDrawText(Left + 2 + i, Top + 2, "\xDB", ATTR(UiTextColor, UiMenuBgColor));
- }
+
+ /* Calculate the width of the bar proper */
+ ProgressBarWidth = (Right - Left) - 3;
+
+ /* First make sure the progress bar text fits */
+ UiTruncateStringEllipsis(ProgressText, ProgressBarWidth - 4);
+ if (Position > Range) Position = Range;
+
+ /* Draw the "Loading..." text */
+ UiDrawCenteredText(Left + 2, Top + 1, Right - 2, Top + 1, ProgressText, ATTR(7, 0));
+
+ /* Draw the percent complete */
+ for (i = 0; i < (Position * ProgressBarWidth) / Range; i++)
+ {
+ /* Use the fill character */
+ UiDrawText(Left + 2 + i, Top + 2, "\xDB", ATTR(UiTextColor, UiMenuBgColor));
+ }
}
VOID
IN ULONG MaxChars)
{
/* If it's too large, just add some ellipsis past the maximum */
- if (strlen(StringText) > MaxChars) strcpy(&StringText[MaxChars - 3], "...");
+ if (strlen(StringText) > MaxChars) strcpy(&StringText[MaxChars - 3], "...");
}
VOID
/* Display under the menu directly */
UiDrawText(0,
- MenuInfo->Bottom + 3,
+ MenuInfo->Bottom + 4,
MenuLineText,
ATTR(UiMenuFgColor, UiMenuBgColor));
}
/* Draw this "empty" string to erase */
UiDrawText(0,
- MenuInfo->Bottom + 3,
+ MenuInfo->Bottom + 4,
MenuLineText,
ATTR(UiMenuFgColor, UiMenuBgColor));
}
for (i = 0; i < MenuInfo->MenuItemCount; i++)
{
/* Check if it's a separator */
- if (!(_stricmp(MenuInfo->MenuItemList[i], "SEPARATOR")))
+ if (MenuInfo->MenuItemList[i] == NULL)
{
/* Draw the separator line */
UiDrawText(MenuInfo->Left,
strcat(MenuLineText, " ");
/* Now append the text string */
- strcat(MenuLineText, MenuInfo->MenuItemList[MenuItemNumber]);
+ if (MenuInfo->MenuItemList[MenuItemNumber])
+ strcat(MenuLineText, MenuInfo->MenuItemList[MenuItemNumber]);
/* If it is a separator */
- if (!(_stricmp(MenuInfo->MenuItemList[MenuItemNumber], "SEPARATOR")))
+ if (MenuInfo->MenuItemList[MenuItemNumber] == NULL)
{
/* Make it a separator line and use menu colors */
memset(MenuLineText, 0, 80);
{
ULONG i;
- /* No GUI status bar text, just minimal text. first to tell the user to choose */
+ /* No GUI status bar text, just minimal text. Show the menu header. */
UiDrawText(0,
MenuInfo->Top - 2,
- "Please select the operating system to start:",
+ MenuInfo->MenuHeader,
ATTR(UiMenuFgColor, UiMenuBgColor));
- /* Now tell him how to choose */
+ /* Now tell the user how to choose */
UiDrawText(0,
MenuInfo->Bottom + 1,
- "Use the up and down arrow keys to move the highlight to "
- "your choice.",
+ "Use \x18 and \x19 to move the highlight to your choice.",
ATTR(UiMenuFgColor, UiMenuBgColor));
UiDrawText(0,
MenuInfo->Bottom + 2,
"Press ENTER to choose.",
ATTR(UiMenuFgColor, UiMenuBgColor));
- /* And offer F8 options */
+ /* And show the menu footer */
UiDrawText(0,
UiScreenHeight - 4,
- "For troubleshooting and advanced startup options for "
- "ReactOS, press F8.",
+ MenuInfo->MenuFooter,
ATTR(UiMenuFgColor, UiMenuBgColor));
/* Draw the menu box */
UiDrawMenuBox(MenuInfo);
/* Draw each line of the menu */
- for (i = 0; i < MenuInfo->MenuItemCount; i++) UiDrawMenuItem(MenuInfo, i);
+ for (i = 0; i < MenuInfo->MenuItemCount; i++)
+ {
+ UiDrawMenuItem(MenuInfo, i);
+ }
+
+ /* Display the boot options if needed */
+ if (MenuInfo->ShowBootOptions)
+ {
+ DisplayBootTimeOptions();
+ }
}
ULONG
UiProcessMenuKeyboardEvent(IN PUI_MENU_INFO MenuInfo,
IN UiMenuKeyPressFilterCallback KeyPressFilter)
{
- ULONG KeyEvent = 0, Selected, Count;
+ ULONG KeyEvent = 0;
+ ULONG Selected, Count;
/* Check for a keypress */
if (MachConsKbHit())
/* Check if the timeout is not already complete */
if (MenuInfo->MenuTimeRemaining != -1)
{
- //
- // Cancel it and remove it
- //
+ /* Cancel it and remove it */
MenuInfo->MenuTimeRemaining = -1;
UiDrawMenuBox(MenuInfo);
}
/* Is it extended? Then get the extended key */
if (!KeyEvent) KeyEvent = MachConsGetCh();
- /* Call the supplied key filter callback function to see if it is going to handle this keypress. */
+ /*
+ * Call the supplied key filter callback function to see
+ * if it is going to handle this keypress.
+ */
if ((KeyPressFilter) && (KeyPressFilter(KeyEvent)))
{
/* It processed the key character, so redraw and exit */
}
/* Process the key */
- if ((KeyEvent == KEY_UP) || (KeyEvent == KEY_DOWN))
+ if ((KeyEvent == KEY_UP ) || (KeyEvent == KEY_DOWN) ||
+ (KeyEvent == KEY_HOME) || (KeyEvent == KEY_END ))
{
/* Get the current selected item and count */
Selected = MenuInfo->SelectedMenuItem;
Count = MenuInfo->MenuItemCount - 1;
- /* Check if this was a key up and there's a selected menu item */
- if ((KeyEvent == KEY_UP) && (Selected))
+ /* Check the key and change the selected menu item */
+ if ((KeyEvent == KEY_UP) && (Selected > 0))
{
- /* Update the menu (Deselect previous item) */
+ /* Deselect previous item and go up */
MenuInfo->SelectedMenuItem--;
UiDrawMenuItem(MenuInfo, Selected);
Selected--;
- /* Skip past any separators */
- if ((Selected) &&
- !(_stricmp(MenuInfo->MenuItemList[Selected], "SEPARATOR")))
+ // Skip past any separators
+ if ((Selected > 0) &&
+ (MenuInfo->MenuItemList[Selected] == NULL))
{
MenuInfo->SelectedMenuItem--;
}
}
+ else if ( ((KeyEvent == KEY_UP) && (Selected == 0)) ||
+ (KeyEvent == KEY_END) )
+ {
+ /* Go to the end */
+ MenuInfo->SelectedMenuItem = Count;
+ UiDrawMenuItem(MenuInfo, Selected);
+ }
else if ((KeyEvent == KEY_DOWN) && (Selected < Count))
{
- /* Update the menu (deselect previous item) */
+ /* Deselect previous item and go down */
MenuInfo->SelectedMenuItem++;
UiDrawMenuItem(MenuInfo, Selected);
Selected++;
- /* Skip past any separators */
+ // Skip past any separators
if ((Selected < Count) &&
- !(_stricmp(MenuInfo->MenuItemList[Selected], "SEPARATOR")))
+ (MenuInfo->MenuItemList[Selected] == NULL))
{
MenuInfo->SelectedMenuItem++;
}
}
+ else if ( ((KeyEvent == KEY_DOWN) && (Selected == Count)) ||
+ (KeyEvent == KEY_HOME) )
+ {
+ /* Go to the beginning */
+ MenuInfo->SelectedMenuItem = 0;
+ UiDrawMenuItem(MenuInfo, Selected);
+ }
/* Select new item and update video buffer */
UiDrawMenuItem(MenuInfo, MenuInfo->SelectedMenuItem);
for (i = 0; i < MenuInfo->MenuItemCount; i++)
{
/* Get the string length and make it become the new width if necessary */
- Length = strlen(MenuInfo->MenuItemList[i]);
- if (Length > Width) Width = Length;
+ if (MenuInfo->MenuItemList[i])
+ {
+ Length = (ULONG)strlen(MenuInfo->MenuItemList[i]);
+ if (Length > Width) Width = Length;
+ }
}
/* Allow room for left & right borders, plus 8 spaces on each side */
}
BOOLEAN
-UiDisplayMenu(IN PCSTR MenuItemList[],
+UiDisplayMenu(IN PCSTR MenuHeader,
+ IN PCSTR MenuFooter,
+ IN BOOLEAN ShowBootOptions,
+ IN PCSTR MenuItemList[],
IN ULONG MenuItemCount,
IN ULONG DefaultMenuItem,
IN LONG MenuTimeOut,
ULONG CurrentClockSecond;
ULONG KeyPress;
+ /*
+ * Before taking any default action if there is no timeout,
+ * check whether the supplied key filter callback function
+ * may handle a specific user keypress. If it does, the
+ * timeout is cancelled.
+ */
+ if (!MenuTimeOut && KeyPressFilter && MachConsKbHit())
+ {
+ /* Get the key */
+ KeyPress = MachConsGetCh();
+
+ /* Is it extended? Then get the extended key */
+ if (!KeyPress) KeyPress = MachConsGetCh();
+
+ /*
+ * Call the supplied key filter callback function to see
+ * if it is going to handle this keypress.
+ */
+ if (KeyPressFilter(KeyPress))
+ {
+ /* It processed the key character, cancel the timeout */
+ MenuTimeOut = -1;
+ }
+ }
+
/* Check if there's no timeout */
if (!MenuTimeOut)
{
}
/* Setup the MENU_INFO structure */
+ MenuInformation.MenuHeader = MenuHeader;
+ MenuInformation.MenuFooter = MenuFooter;
+ MenuInformation.ShowBootOptions = ShowBootOptions;
MenuInformation.MenuItemList = MenuItemList;
MenuInformation.MenuItemCount = MenuItemCount;
MenuInformation.MenuTimeRemaining = MenuTimeOut;
if (CanEscape && KeyPress == KEY_ESC) return FALSE;
/* Check if there is a countdown */
- if (MenuInformation.MenuTimeRemaining)
+ if (MenuInformation.MenuTimeRemaining > 0)
{
/* Get the updated time, seconds only */
CurrentClockSecond = ArcGetTime()->Second;
UiDrawMenuBox(&MenuInformation);
}
}
- else
+ else if (MenuInformation.MenuTimeRemaining == 0)
{
/* A time out occurred, exit this loop and return default OS */
break;