ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

directui.c
Go to the documentation of this file.
00001 /*
00002  * PROJECT:         ReactOS Boot Loader
00003  * LICENSE:         BSD - See COPYING.ARM in the top level directory
00004  * FILE:            boot/freeldr/freeldr/ui/directui.c
00005  * PURPOSE:         FreeLDR UI Routines
00006  * PROGRAMMERS:     ReactOS Portable Systems Group
00007  */
00008 #ifdef _M_ARM
00009 
00010 /* INCLUDES *******************************************************************/
00011 
00012 #include <freeldr.h>
00013 #include <debug.h>
00014 
00015 /* GLOBALS ********************************************************************/
00016 
00017 /* FUNCTIONS ******************************************************************/
00018 
00019 ULONG UiScreenWidth;
00020 ULONG UiScreenHeight;
00021 UCHAR UiMenuFgColor = COLOR_GRAY;
00022 UCHAR UiMenuBgColor = COLOR_BLACK;
00023 UCHAR UiTextColor = COLOR_GRAY;
00024 UCHAR UiSelectedTextColor = COLOR_BLACK;
00025 UCHAR UiSelectedTextBgColor = COLOR_GRAY;
00026 CHAR UiTimeText[260] = "Seconds until highlighted choice will be started automatically:   ";
00027 
00028 INT
00029 TuiPrintf(const char *Format,
00030           ...)
00031 {
00032     int i;
00033     int Length;
00034     va_list ap;
00035     CHAR Buffer[512];
00036 
00037     va_start(ap, Format);
00038     Length = _vsnprintf(Buffer, sizeof(Buffer), Format, ap);
00039     va_end(ap);
00040 
00041     if (Length == -1) Length = sizeof(Buffer);
00042 
00043     for (i = 0; i < Length; i++)
00044     {
00045         MachConsPutChar(Buffer[i]);
00046     }
00047 
00048     return Length;
00049 }
00050 
00051 BOOLEAN
00052 UiInitialize(IN BOOLEAN ShowGui)
00053 {
00054     ULONG Depth;
00055     
00056     /* Nothing to do */
00057     if (!ShowGui) return TRUE;
00058 
00059     /* Set mode and query size */
00060     MachVideoSetDisplayMode(NULL, TRUE);
00061     MachVideoGetDisplaySize(&UiScreenWidth, &UiScreenHeight, &Depth);
00062     return TRUE;
00063 }
00064 
00065 VOID
00066 UiUnInitialize(IN PCSTR BootText)
00067 {
00068     /* Nothing to do */
00069     return;
00070 }
00071 
00072 VOID
00073 UiDrawBackdrop(VOID)
00074 {
00075     /* Clear the screen */
00076     MachVideoClearScreen(ATTR(COLOR_WHITE, COLOR_BLACK));
00077 }
00078 
00079 VOID
00080 UiDrawText(IN ULONG X,
00081            IN ULONG Y,
00082            IN PCSTR Text,
00083            IN UCHAR Attr)
00084 {
00085     ULONG i, j;
00086 
00087     /* Draw the text character by character, but don't exceed the width */
00088     for (i = X, j = 0; Text[j] && i < UiScreenWidth; i++, j++)
00089     {
00090         /* Write the character */
00091         MachVideoPutChar(Text[j], Attr, i, Y);
00092     }
00093 }
00094 
00095 VOID
00096 UiDrawCenteredText(IN ULONG Left,
00097                    IN ULONG Top,
00098                    IN ULONG Right,
00099                    IN ULONG Bottom,
00100                    IN PCSTR TextString,
00101                    IN UCHAR Attr)
00102 {
00103     ULONG TextLength, BoxWidth, BoxHeight, LineBreakCount, Index, LastIndex;
00104     ULONG RealLeft, RealTop, X, Y;
00105     CHAR Temp[2];
00106 
00107     /* Query text length */
00108     TextLength = strlen(TextString);
00109 
00110     /* Count the new lines and the box width */
00111     LineBreakCount = 0;
00112     BoxWidth = 0;
00113     LastIndex = 0;
00114     for (Index=0; Index < TextLength; Index++)
00115     {
00116         /* Scan for new lines */
00117         if (TextString[Index] == '\n')
00118         {
00119             /* Remember the new line */
00120             LastIndex = Index;
00121             LineBreakCount++;
00122         }
00123         else
00124         {
00125             /* Check for new larger box width */
00126             if ((Index - LastIndex) > BoxWidth)
00127             {
00128                 /* Update it */
00129                 BoxWidth = (Index - LastIndex);
00130             }
00131         }
00132     }
00133 
00134     /* Base the box height on the number of lines */
00135     BoxHeight = LineBreakCount + 1;
00136 
00137     /* Create the centered coordinates */
00138     RealLeft = (((Right - Left) - BoxWidth) / 2) + Left;
00139     RealTop = (((Bottom - Top) - BoxHeight) / 2) + Top;
00140 
00141     /* Now go for a second scan */
00142     LastIndex = 0;
00143     for (Index=0; Index < TextLength; Index++)
00144     {
00145         /* Look for new lines again */
00146         if (TextString[Index] == '\n')
00147         {
00148             /* Update where the text should start */
00149             RealTop++;
00150             LastIndex = 0;
00151         }
00152         else
00153         {
00154             /* We've got a line of text to print, do it */
00155             X = RealLeft + LastIndex;
00156             Y = RealTop;
00157             LastIndex++;
00158             Temp[0] = TextString[Index];
00159             Temp[1] = 0;
00160             UiDrawText(X, Y, Temp, Attr);
00161         }
00162     }
00163 }
00164 
00165 VOID
00166 UiDrawStatusText(IN PCSTR StatusText)
00167 {
00168     return;
00169 }
00170 
00171 VOID
00172 UiInfoBox(IN PCSTR MessageText)
00173 {
00174     TuiPrintf(MessageText);
00175 }
00176 
00177 VOID
00178 UiMessageBox(IN PCSTR MessageText)
00179 {
00180     TuiPrintf(MessageText);
00181 }
00182 
00183 VOID
00184 UiMessageBoxCritical(IN PCSTR MessageText)
00185 {
00186     TuiPrintf(MessageText);
00187 }
00188 
00189 VOID
00190 UiDrawProgressBarCenter(IN ULONG Position,
00191                         IN ULONG Range,
00192                         IN PCHAR ProgressText)
00193 {
00194     ULONG Left, Top, Right, Bottom, Width, Height;
00195 
00196     /* Build the coordinates and sizes */
00197     Height = 2;
00198     Width = UiScreenWidth;
00199     Left = 0;
00200     Right = (Left + Width) - 1;
00201     Top = UiScreenHeight - Height - 4;
00202     Bottom = Top + Height + 1;
00203 
00204     /* Draw the progress bar */
00205     UiDrawProgressBar(Left, Top, Right, Bottom, Position, Range, ProgressText);
00206 }
00207 
00208 VOID
00209 UiDrawProgressBar(IN ULONG Left,
00210                   IN ULONG Top,
00211                   IN ULONG Right,
00212                   IN ULONG Bottom, 
00213                   IN ULONG Position,
00214                   IN ULONG Range,
00215                   IN PCHAR ProgressText)
00216 {
00217     ULONG i, ProgressBarWidth;
00218     
00219     /* Calculate the width of the bar proper */
00220     ProgressBarWidth = (Right - Left) - 3;
00221 
00222     /* First make sure the progress bar text fits */
00223     UiTruncateStringEllipsis(ProgressText, ProgressBarWidth - 4);
00224     if (Position > Range) Position = Range;
00225 
00226     /* Draw the "Loading..." text */
00227     UiDrawCenteredText(Left + 2, Top + 1, Right - 2, Top + 1, ProgressText, ATTR(7, 0));
00228 
00229     /* Draw the percent complete */
00230     for (i = 0; i < (Position * ProgressBarWidth) / Range; i++)
00231     {
00232         /* Use the fill character */
00233         UiDrawText(Left + 2 + i, Top + 2, "\xDB", ATTR(UiTextColor, UiMenuBgColor));
00234     }
00235 }
00236 
00237 VOID
00238 UiShowMessageBoxesInSection(IN PCSTR SectionName)
00239 {
00240     return;
00241 }
00242 
00243 VOID
00244 UiTruncateStringEllipsis(IN PCHAR StringText,
00245                          IN ULONG MaxChars)
00246 {
00247     /* If it's too large, just add some ellipsis past the maximum */
00248     if (strlen(StringText) > MaxChars) strcpy(&StringText[MaxChars - 3], "...");
00249 }
00250 
00251 VOID
00252 NTAPI
00253 UiDrawMenuBox(IN PUI_MENU_INFO MenuInfo)
00254 {
00255     CHAR MenuLineText[80], TempString[80];
00256     ULONG i;
00257 
00258     /* If there is a timeout draw the time remaining */
00259     if (MenuInfo->MenuTimeRemaining >= 0)
00260     {
00261         /* Copy the integral time text string, and remove the last 2 chars */
00262         strcpy(TempString, UiTimeText);
00263         i = strlen(TempString);
00264         TempString[i - 2] = 0;
00265 
00266         /* Display the first part of the string and the remaining time */
00267         strcpy(MenuLineText, TempString);
00268         _itoa(MenuInfo->MenuTimeRemaining, TempString, 10);
00269         strcat(MenuLineText, TempString);
00270 
00271         /* Add the last 2 chars */
00272         strcat(MenuLineText, &UiTimeText[i - 2]);
00273 
00274         /* Display under the menu directly */
00275         UiDrawText(0,
00276                    MenuInfo->Bottom + 3,
00277                    MenuLineText,
00278                    ATTR(UiMenuFgColor, UiMenuBgColor));
00279     }
00280     else
00281     {
00282         /* Erase the timeout string with spaces, and 0-terminate for sure */
00283         for (i=0; i<sizeof(MenuLineText)-1; i++)
00284         {
00285             MenuLineText[i] = ' ';
00286         }
00287         MenuLineText[sizeof(MenuLineText)-1] = 0;
00288 
00289         /* Draw this "empty" string to erase */
00290         UiDrawText(0,
00291                    MenuInfo->Bottom + 3,
00292                    MenuLineText,
00293                    ATTR(UiMenuFgColor, UiMenuBgColor));
00294     }
00295 
00296     /* Loop each item */
00297     for (i = 0; i < MenuInfo->MenuItemCount; i++)
00298     {
00299         /* Check if it's a separator */
00300         if (!(_stricmp(MenuInfo->MenuItemList[i], "SEPARATOR")))
00301         {
00302             /* Draw the separator line */
00303             UiDrawText(MenuInfo->Left,
00304                        MenuInfo->Top + i + 1,
00305                        "\xC7",
00306                        ATTR(UiMenuFgColor, UiMenuBgColor));
00307             UiDrawText(MenuInfo->Right,
00308                        MenuInfo->Top + i + 1,
00309                        "\xB6",
00310                        ATTR(UiMenuFgColor, UiMenuBgColor));
00311         }
00312     }
00313 }
00314 
00315 VOID
00316 NTAPI
00317 UiDrawMenuItem(IN PUI_MENU_INFO MenuInfo,
00318                IN ULONG MenuItemNumber)
00319 {
00320     CHAR MenuLineText[80];
00321     UCHAR Attribute = ATTR(UiTextColor, UiMenuBgColor);
00322 
00323     /* Simply left-align it */
00324     MenuLineText[0] = '\0';
00325     strcat(MenuLineText, "    ");
00326 
00327     /* Now append the text string */
00328     strcat(MenuLineText, MenuInfo->MenuItemList[MenuItemNumber]);
00329 
00330     /* If it is a separator */
00331     if (!(_stricmp(MenuInfo->MenuItemList[MenuItemNumber], "SEPARATOR")))
00332     {
00333         /* Make it a separator line and use menu colors */
00334         memset(MenuLineText, 0, 80);
00335         memset(MenuLineText, 0xC4, (MenuInfo->Right - MenuInfo->Left - 1));
00336         Attribute = ATTR(UiMenuFgColor, UiMenuBgColor);
00337     }
00338     else if (MenuItemNumber == MenuInfo->SelectedMenuItem)
00339     {
00340         /*  If this is the selected item, use the selected colors */
00341         Attribute = ATTR(UiSelectedTextColor, UiSelectedTextBgColor);
00342     }
00343 
00344     /* Draw the item */
00345     UiDrawText(MenuInfo->Left + 1,
00346                MenuInfo->Top + 1 + MenuItemNumber,
00347                MenuLineText,
00348                Attribute);
00349 }
00350 
00351 VOID
00352 UiDrawMenu(IN PUI_MENU_INFO MenuInfo)
00353 {
00354     ULONG i;
00355 
00356     /* No GUI status bar text, just minimal text. first to tell the user to choose */
00357     UiDrawText(0,
00358                MenuInfo->Top - 2,
00359                "Please select the operating system to start:",
00360                ATTR(UiMenuFgColor, UiMenuBgColor));
00361 
00362     /* Now tell him how to choose */
00363     UiDrawText(0,
00364                MenuInfo->Bottom + 1,
00365                "Use the up and down arrow keys to move the highlight to "
00366                "your choice.",
00367                ATTR(UiMenuFgColor, UiMenuBgColor));
00368     UiDrawText(0,
00369                MenuInfo->Bottom + 2,
00370                "Press ENTER to choose.",
00371                ATTR(UiMenuFgColor, UiMenuBgColor));
00372 
00373     /* And offer F8 options */
00374     UiDrawText(0,
00375                UiScreenHeight - 4,
00376                "For troubleshooting and advanced startup options for "
00377                "ReactOS, press F8.",
00378                ATTR(UiMenuFgColor, UiMenuBgColor));
00379 
00380     /* Draw the menu box */
00381     UiDrawMenuBox(MenuInfo);
00382 
00383     /* Draw each line of the menu */
00384     for (i = 0; i < MenuInfo->MenuItemCount; i++) UiDrawMenuItem(MenuInfo, i);
00385 }
00386 
00387 ULONG
00388 NTAPI
00389 UiProcessMenuKeyboardEvent(IN PUI_MENU_INFO MenuInfo,
00390                            IN UiMenuKeyPressFilterCallback KeyPressFilter)
00391 {
00392     ULONG KeyEvent = 0, Selected, Count;
00393 
00394     /* Check for a keypress */
00395     if (MachConsKbHit())
00396     {
00397         /* Check if the timeout is not already complete */
00398         if (MenuInfo->MenuTimeRemaining != -1)
00399         {
00400             //
00401             // Cancel it and remove it
00402             //
00403             MenuInfo->MenuTimeRemaining = -1;
00404             UiDrawMenuBox(MenuInfo);
00405         }
00406 
00407         /* Get the key */
00408         KeyEvent = MachConsGetCh();
00409 
00410         /* Is it extended? Then get the extended key */
00411         if (!KeyEvent) KeyEvent = MachConsGetCh();
00412 
00413         /* Call the supplied key filter callback function to see if it is going to handle this keypress. */
00414         if ((KeyPressFilter) && (KeyPressFilter(KeyEvent)))
00415         {
00416             /* It processed the key character, so redraw and exit */
00417             UiDrawMenu(MenuInfo);
00418             return 0;
00419         }
00420 
00421         /* Process the key */
00422         if ((KeyEvent == KEY_UP) || (KeyEvent == KEY_DOWN))
00423         {
00424             /* Get the current selected item and count */
00425             Selected = MenuInfo->SelectedMenuItem;
00426             Count = MenuInfo->MenuItemCount - 1;
00427 
00428             /* Check if this was a key up and there's a selected menu item */
00429             if ((KeyEvent == KEY_UP) && (Selected))
00430             {
00431                 /* Update the menu (Deselect previous item) */
00432                 MenuInfo->SelectedMenuItem--;
00433                 UiDrawMenuItem(MenuInfo, Selected);
00434                 Selected--;
00435 
00436                 /* Skip past any separators */
00437                 if ((Selected) &&
00438                     !(_stricmp(MenuInfo->MenuItemList[Selected], "SEPARATOR")))
00439                 {
00440                     MenuInfo->SelectedMenuItem--;
00441                 }
00442             }
00443             else if ((KeyEvent == KEY_DOWN) && (Selected < Count))
00444             {
00445                 /* Update the menu (deselect previous item) */
00446                 MenuInfo->SelectedMenuItem++;
00447                 UiDrawMenuItem(MenuInfo, Selected);
00448                 Selected++;
00449 
00450                 /* Skip past any separators */
00451                 if ((Selected < Count) &&
00452                     !(_stricmp(MenuInfo->MenuItemList[Selected], "SEPARATOR")))
00453                 {
00454                     MenuInfo->SelectedMenuItem++;
00455                 }
00456             }
00457 
00458             /* Select new item and update video buffer */
00459             UiDrawMenuItem(MenuInfo, MenuInfo->SelectedMenuItem);
00460         }
00461     }
00462 
00463     /*  Return the pressed key */
00464     return KeyEvent;
00465 }
00466 
00467 VOID
00468 NTAPI
00469 UiCalcMenuBoxSize(IN PUI_MENU_INFO MenuInfo)
00470 {
00471     ULONG i, Width = 0, Height, Length;
00472 
00473     /* Height is the menu item count plus 2 (top border & bottom border) */
00474     Height = MenuInfo->MenuItemCount + 2;
00475     Height -= 1; // Height is zero-based
00476 
00477     /* Loop every item */
00478     for (i = 0; i < MenuInfo->MenuItemCount; i++)
00479     {
00480         /* Get the string length and make it become the new width if necessary */
00481         Length = strlen(MenuInfo->MenuItemList[i]);
00482         if (Length > Width) Width = Length;
00483     }
00484 
00485     /* Allow room for left & right borders, plus 8 spaces on each side */
00486     Width += 18;
00487 
00488     /* Put the menu in the default left-corner position */
00489     MenuInfo->Left = -1;
00490     MenuInfo->Top = 4;
00491 
00492     /* The other margins are the same */
00493     MenuInfo->Right = (MenuInfo->Left) + Width;
00494     MenuInfo->Bottom = (MenuInfo->Top) + Height;
00495 }
00496 
00497 BOOLEAN
00498 UiDisplayMenu(IN PCSTR MenuItemList[],
00499               IN ULONG MenuItemCount,
00500               IN ULONG DefaultMenuItem,
00501               IN LONG MenuTimeOut,
00502               OUT PULONG SelectedMenuItem,
00503               IN BOOLEAN CanEscape,
00504               IN UiMenuKeyPressFilterCallback KeyPressFilter)
00505 {
00506     UI_MENU_INFO MenuInformation;
00507     ULONG LastClockSecond;
00508     ULONG CurrentClockSecond;
00509     ULONG KeyPress;
00510 
00511     /* Check if there's no timeout */
00512     if (!MenuTimeOut)
00513     {
00514         /* Return the default selected item */
00515         if (SelectedMenuItem) *SelectedMenuItem = DefaultMenuItem;
00516         return TRUE;
00517     }
00518 
00519     /* Setup the MENU_INFO structure */
00520     MenuInformation.MenuItemList = MenuItemList;
00521     MenuInformation.MenuItemCount = MenuItemCount;
00522     MenuInformation.MenuTimeRemaining = MenuTimeOut;
00523     MenuInformation.SelectedMenuItem = DefaultMenuItem;
00524 
00525     /* Calculate the size of the menu box */
00526     UiCalcMenuBoxSize(&MenuInformation);
00527 
00528     /* Draw the menu */
00529     UiDrawMenu(&MenuInformation);
00530 
00531     /* Get the current second of time */
00532     LastClockSecond = ArcGetTime()->Second;
00533 
00534     /* Process keys */
00535     while (TRUE)
00536     {
00537         /* Process key presses */
00538         KeyPress = UiProcessMenuKeyboardEvent(&MenuInformation,
00539                                               KeyPressFilter);
00540 
00541         /* Check for ENTER or ESC */
00542         if (KeyPress == KEY_ENTER) break;
00543         if (CanEscape && KeyPress == KEY_ESC) return FALSE;
00544 
00545         /* Check if there is a countdown */
00546         if (MenuInformation.MenuTimeRemaining)
00547         {
00548             /* Get the updated time, seconds only */
00549             CurrentClockSecond = ArcGetTime()->Second;
00550 
00551             /* Check if more then a second has now elapsed */
00552             if (CurrentClockSecond != LastClockSecond)
00553             {
00554                 /* Update the time information */
00555                 LastClockSecond = CurrentClockSecond;
00556                 MenuInformation.MenuTimeRemaining--;
00557 
00558                 /* Update the menu */
00559                 UiDrawMenuBox(&MenuInformation);
00560             }
00561         }
00562         else
00563         {
00564             /* A time out occurred, exit this loop and return default OS */
00565             break;
00566         }
00567     }
00568 
00569     /* Return the selected item */
00570     if (SelectedMenuItem) *SelectedMenuItem = MenuInformation.SelectedMenuItem;
00571     return TRUE;
00572 }
00573 
00574 #endif

Generated on Sun May 27 2012 04:19:17 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.