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

tuimenu.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       See COPYING in the top level directory
00003  * PROJECT:         FreeLoader
00004  * FILE:            freeldr/ui/tuimenu.c
00005  * PURPOSE:         UI Menu Functions
00006  * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net)
00007  *                  Brian Palmer (brianp@sginet.com)
00008  */
00009 
00010 /* INCLUDES ******************************************************************/
00011 #ifndef _M_ARM
00012 #include <freeldr.h>
00013 
00014 /* FUNCTIONS *****************************************************************/
00015 
00016 BOOLEAN
00017 TuiDisplayMenu(PCSTR MenuItemList[],
00018                ULONG MenuItemCount,
00019                ULONG DefaultMenuItem,
00020                LONG MenuTimeOut,
00021                ULONG* SelectedMenuItem,
00022                BOOLEAN CanEscape,
00023                UiMenuKeyPressFilterCallback KeyPressFilter)
00024 {
00025     UI_MENU_INFO MenuInformation;
00026     ULONG LastClockSecond;
00027     ULONG CurrentClockSecond;
00028     ULONG KeyPress;
00029 
00030     //
00031     // Check if there's no timeout
00032     if (!MenuTimeOut)
00033     {
00034         //
00035         // Return the default selected item
00036         //
00037         if (SelectedMenuItem) *SelectedMenuItem = DefaultMenuItem;
00038         return TRUE;
00039     }
00040 
00041     //
00042     // Setup the MENU_INFO structure
00043     //
00044     MenuInformation.MenuItemList = MenuItemList;
00045     MenuInformation.MenuItemCount = MenuItemCount;
00046     MenuInformation.MenuTimeRemaining = MenuTimeOut;
00047     MenuInformation.SelectedMenuItem = DefaultMenuItem;
00048 
00049     //
00050     // Calculate the size of the menu box
00051     //
00052     TuiCalcMenuBoxSize(&MenuInformation);
00053 
00054     //
00055     // Draw the menu
00056     //
00057     UiVtbl.DrawMenu(&MenuInformation);
00058 
00059     //
00060     // Get the current second of time
00061     //
00062     LastClockSecond = ArcGetTime()->Second;
00063 
00064     //
00065     // Process keys
00066     //
00067     while (TRUE)
00068     {
00069         //
00070         // Process key presses
00071         //
00072         KeyPress = TuiProcessMenuKeyboardEvent(&MenuInformation,
00073                                                KeyPressFilter);
00074 
00075         //
00076         // Check for ENTER or ESC
00077         //
00078         if (KeyPress == KEY_ENTER) break;
00079         if (CanEscape && KeyPress == KEY_ESC) return FALSE;
00080 
00081         //
00082         // Update the date & time
00083         //
00084         TuiUpdateDateTime();
00085         VideoCopyOffScreenBufferToVRAM();
00086 
00087         //
00088         // Check if there is a countdown
00089         //
00090         if (MenuInformation.MenuTimeRemaining)
00091         {
00092             //
00093             // Get the updated time, seconds only
00094             //
00095             CurrentClockSecond = ArcGetTime()->Second;
00096 
00097             //
00098             // Check if more then a second has now elapsed
00099             //
00100             if (CurrentClockSecond != LastClockSecond)
00101             {
00102                 //
00103                 // Update the time information
00104                 //
00105                 LastClockSecond = CurrentClockSecond;
00106                 MenuInformation.MenuTimeRemaining--;
00107 
00108                 //
00109                 // Update the menu
00110                 //
00111                 TuiDrawMenuBox(&MenuInformation);
00112                 VideoCopyOffScreenBufferToVRAM();
00113             }
00114         }
00115         else
00116         {
00117             //
00118             // A time out occurred, exit this loop and return default OS
00119             //
00120             break;
00121         }
00122 
00123         MachHwIdle();
00124     }
00125 
00126     //
00127     // Return the selected item
00128     //
00129     if (SelectedMenuItem) *SelectedMenuItem = MenuInformation.SelectedMenuItem;
00130     return TRUE;
00131 }
00132 
00133 VOID
00134 NTAPI
00135 TuiCalcMenuBoxSize(PUI_MENU_INFO MenuInfo)
00136 {
00137     ULONG i;
00138     ULONG Width = 0;
00139     ULONG Height;
00140     ULONG Length;
00141 
00142     //
00143     // Height is the menu item count plus 2 (top border & bottom border)
00144     //
00145     Height = MenuInfo->MenuItemCount + 2;
00146     Height -= 1; // Height is zero-based
00147 
00148     //
00149     // Loop every item
00150     //
00151     for(i = 0; i < MenuInfo->MenuItemCount; i++)
00152     {
00153         //
00154         // Get the string length and make it become the new width if necessary
00155         //
00156         Length = (ULONG)strlen(MenuInfo->MenuItemList[i]);
00157         if (Length > Width) Width = Length;
00158     }
00159 
00160     //
00161     // Allow room for left & right borders, plus 8 spaces on each side
00162     //
00163     Width += 18;
00164 
00165     //
00166     // Check if we're drawing a centered menu
00167     //
00168     if (UiCenterMenu)
00169     {
00170         //
00171         // Calculate the menu box area for a centered menu
00172         //
00173         MenuInfo->Left = (UiScreenWidth - Width) / 2;
00174         MenuInfo->Top = (((UiScreenHeight - TUI_TITLE_BOX_CHAR_HEIGHT) -
00175                           Height) / 2) + TUI_TITLE_BOX_CHAR_HEIGHT;
00176     }
00177     else
00178     {
00179         //
00180         // Put the menu in the default left-corner position
00181         //
00182         MenuInfo->Left = -1;
00183         MenuInfo->Top = 4;
00184     }
00185 
00186     //
00187     // The other margins are the same
00188     //
00189     MenuInfo->Right = (MenuInfo->Left) + Width;
00190     MenuInfo->Bottom = (MenuInfo->Top) + Height;
00191 }
00192 
00193 VOID
00194 TuiDrawMenu(PUI_MENU_INFO MenuInfo)
00195 {
00196     ULONG i;
00197 
00198     //
00199     // Draw the backdrop
00200     //
00201     UiDrawBackdrop();
00202 
00203     //
00204     // Update the status bar
00205     //
00206     UiVtbl.DrawStatusText("Use \x18\x19 to select, then press ENTER.");
00207 
00208     //
00209     // Draw the menu box
00210     //
00211     TuiDrawMenuBox(MenuInfo);
00212 
00213     //
00214     // Draw each line of the menu
00215     //
00216     for (i = 0; i < MenuInfo->MenuItemCount; i++) TuiDrawMenuItem(MenuInfo, i);
00217     VideoCopyOffScreenBufferToVRAM();
00218 }
00219 
00220 VOID
00221 NTAPI
00222 TuiDrawMenuBox(PUI_MENU_INFO MenuInfo)
00223 {
00224     CHAR MenuLineText[80];
00225     CHAR TempString[80];
00226     ULONG i;
00227 
00228     //
00229     // Draw the menu box if requested
00230     //
00231     if (UiMenuBox)
00232     {
00233         UiDrawBox(MenuInfo->Left,
00234                   MenuInfo->Top,
00235                   MenuInfo->Right,
00236                   MenuInfo->Bottom,
00237                   D_VERT,
00238                   D_HORZ,
00239                   FALSE,        // Filled
00240                   TRUE,        // Shadow
00241                   ATTR(UiMenuFgColor, UiMenuBgColor));
00242     }
00243 
00244     //
00245     // If there is a timeout draw the time remaining
00246     //
00247     if (MenuInfo->MenuTimeRemaining >= 0)
00248     {
00249         //
00250         // Copy the integral time text string, and remove the last 2 chars
00251         //
00252         strcpy(TempString, UiTimeText);
00253         i = (ULONG)strlen(TempString);
00254         TempString[i - 2] = 0;
00255 
00256         //
00257         // Display the first part of the string and the remaining time
00258         //
00259         strcpy(MenuLineText, TempString);
00260         _itoa(MenuInfo->MenuTimeRemaining, TempString, 10);
00261         strcat(MenuLineText, TempString);
00262 
00263         //
00264         // Add the last 2 chars
00265         //
00266         strcat(MenuLineText, &UiTimeText[i - 2]);
00267 
00268         //
00269         // Check if this is a centered menu
00270         //
00271         if (UiCenterMenu)
00272         {
00273             //
00274             // Display it in the center of the menu
00275             //
00276             UiDrawText(MenuInfo->Right - (ULONG)strlen(MenuLineText) - 1,
00277                        MenuInfo->Bottom,
00278                        MenuLineText,
00279                        ATTR(UiMenuFgColor, UiMenuBgColor));
00280         }
00281         else
00282         {
00283             //
00284             // Display under the menu directly
00285             //
00286             UiDrawText(0,
00287                        MenuInfo->Bottom + 3,
00288                        MenuLineText,
00289                        ATTR(UiMenuFgColor, UiMenuBgColor));
00290         }
00291     }
00292     else
00293     {
00294         //
00295         // Erase the timeout string with spaces, and 0-terminate for sure
00296         //
00297         for (i=0; i<sizeof(MenuLineText)-1; i++)
00298         {
00299             MenuLineText[i] = ' ';
00300         }
00301         MenuLineText[sizeof(MenuLineText)-1] = 0;
00302 
00303         //
00304         // Draw this "empty" string to erase
00305         //
00306         if (UiCenterMenu)
00307         {
00308             UiDrawText(MenuInfo->Right - (ULONG)strlen(MenuLineText) - 1,
00309                        MenuInfo->Bottom,
00310                        MenuLineText,
00311                        ATTR(UiMenuFgColor, UiMenuBgColor));
00312         }
00313         else
00314         {
00315             UiDrawText(0,
00316                        MenuInfo->Bottom + 3,
00317                        MenuLineText,
00318                        ATTR(UiMenuFgColor, UiMenuBgColor));
00319         }
00320     }
00321 
00322     //
00323     // Loop each item
00324     //
00325     for (i = 0; i < MenuInfo->MenuItemCount; i++)
00326     {
00327         //
00328         // Check if it's a separator
00329         //
00330         if (!(_stricmp(MenuInfo->MenuItemList[i], "SEPARATOR")))
00331         {
00332             //
00333             // Draw the separator line
00334             //
00335             UiDrawText(MenuInfo->Left,
00336                        MenuInfo->Top + i + 1,
00337                        "\xC7",
00338                        ATTR(UiMenuFgColor, UiMenuBgColor));
00339             UiDrawText(MenuInfo->Right,
00340                        MenuInfo->Top + i + 1,
00341                        "\xB6",
00342                        ATTR(UiMenuFgColor, UiMenuBgColor));
00343         }
00344     }
00345 }
00346 
00347 VOID
00348 NTAPI
00349 TuiDrawMenuItem(PUI_MENU_INFO MenuInfo,
00350                 ULONG MenuItemNumber)
00351 {
00352     ULONG i;
00353     CHAR MenuLineText[80];
00354     ULONG SpaceTotal;
00355     ULONG SpaceLeft;
00356     ULONG SpaceRight = 0;
00357     UCHAR Attribute = ATTR(UiTextColor, UiMenuBgColor);
00358 
00359     //
00360     // Check if using centered menu
00361     //
00362     if (UiCenterMenu)
00363     {
00364         //
00365         // We will want the string centered so calculate
00366         // how many spaces will be to the left and right
00367         //
00368         SpaceTotal = (MenuInfo->Right - MenuInfo->Left - 2) -
00369                      (ULONG)strlen(MenuInfo->MenuItemList[MenuItemNumber]);
00370         SpaceLeft = (SpaceTotal / 2) + 1;
00371         SpaceRight = (SpaceTotal - SpaceLeft) + 1;
00372 
00373         //
00374         // Insert the spaces on the left
00375         //
00376         for (i = 0; i < SpaceLeft; i++) MenuLineText[i] = ' ';
00377         MenuLineText[i] = '\0';
00378     }
00379     else
00380     {
00381         //
00382         // Simply left-align it
00383         //
00384         MenuLineText[0] = '\0';
00385         strcat(MenuLineText, "    ");
00386     }
00387 
00388     //
00389     // Now append the text string
00390     //
00391     strcat(MenuLineText, MenuInfo->MenuItemList[MenuItemNumber]);
00392 
00393     //
00394     // Check if using centered menu, and add spaces on the right if so
00395     //
00396     if (UiCenterMenu) for (i=0; i < SpaceRight; i++) strcat(MenuLineText, " ");
00397 
00398     //
00399     // If it is a separator
00400     //
00401     if (!(_stricmp(MenuInfo->MenuItemList[MenuItemNumber], "SEPARATOR")))
00402     {
00403         //
00404         // Make it a separator line and use menu colors
00405         //
00406         memset(MenuLineText, 0, 80);
00407         memset(MenuLineText, 0xC4, (MenuInfo->Right - MenuInfo->Left - 1));
00408         Attribute = ATTR(UiMenuFgColor, UiMenuBgColor);
00409     }
00410     else if (MenuItemNumber == MenuInfo->SelectedMenuItem)
00411     {
00412         //
00413         // If this is the selected item, use the selected colors
00414         //
00415         Attribute = ATTR(UiSelectedTextColor, UiSelectedTextBgColor);
00416     }
00417 
00418     //
00419     // Draw the item
00420     //
00421     UiDrawText(MenuInfo->Left + 1,
00422                MenuInfo->Top + 1 + MenuItemNumber,
00423                MenuLineText,
00424                Attribute);
00425 }
00426 
00427 ULONG
00428 NTAPI
00429 TuiProcessMenuKeyboardEvent(PUI_MENU_INFO MenuInfo,
00430                             UiMenuKeyPressFilterCallback KeyPressFilter)
00431 {
00432     ULONG KeyEvent = 0;
00433     ULONG Selected, Count;
00434 
00435     //
00436     // Check for a keypress
00437     //
00438     if (MachConsKbHit())
00439     {
00440         //
00441         // Check if the timeout is not already complete
00442         //
00443         if (MenuInfo->MenuTimeRemaining != -1)
00444         {
00445             //
00446             // Cancel it and remove it
00447             //
00448             MenuInfo->MenuTimeRemaining = -1;
00449             TuiDrawMenuBox(MenuInfo); // FIXME: Remove for minimal UI too
00450         }
00451 
00452         //
00453         // Get the key
00454         //
00455         KeyEvent = MachConsGetCh();
00456 
00457         //
00458         // Is it extended? Then get the extended key
00459         //
00460         if (!KeyEvent) KeyEvent = MachConsGetCh();
00461 
00462         //
00463         // Call the supplied key filter callback function to see
00464         // if it is going to handle this keypress.
00465         //
00466         if ((KeyPressFilter) && (KeyPressFilter(KeyEvent)))
00467         {
00468             //
00469             // It processed the key character, so redraw and exit
00470             //
00471             UiVtbl.DrawMenu(MenuInfo);
00472             return 0;
00473         }
00474 
00475         //
00476         // Process the key
00477         //
00478         if ((KeyEvent == KEY_UP) || (KeyEvent == KEY_DOWN))
00479         {
00480             //
00481             // Get the current selected item and count
00482             //
00483             Selected = MenuInfo->SelectedMenuItem;
00484             Count = MenuInfo->MenuItemCount - 1;
00485 
00486             //
00487             // Check if this was a key up and there's a selected menu item
00488             //
00489             if ((KeyEvent == KEY_UP) && (Selected))
00490             {
00491                 //
00492                 // Update the menu (Deselect previous item)
00493                 //
00494                 MenuInfo->SelectedMenuItem--;
00495                 TuiDrawMenuItem(MenuInfo, Selected);
00496                 Selected--;
00497 
00498                 // Skip past any separators
00499                 if ((Selected) &&
00500                     !(_stricmp(MenuInfo->MenuItemList[Selected], "SEPARATOR")))
00501                 {
00502                     MenuInfo->SelectedMenuItem--;
00503                 }
00504             }
00505             else if ((KeyEvent == KEY_DOWN) && (Selected < Count))
00506             {
00507                 //
00508                 // Update the menu (deselect previous item)
00509                 //
00510                 MenuInfo->SelectedMenuItem++;
00511                 TuiDrawMenuItem(MenuInfo, Selected);
00512                 Selected++;
00513 
00514                 // Skip past any separators
00515                 if ((Selected < Count) &&
00516                     !(_stricmp(MenuInfo->MenuItemList[Selected], "SEPARATOR")))
00517                 {
00518                     MenuInfo->SelectedMenuItem++;
00519                 }
00520             }
00521 
00522             //
00523             // Select new item and update video buffer
00524             //
00525             TuiDrawMenuItem(MenuInfo, MenuInfo->SelectedMenuItem);
00526             VideoCopyOffScreenBufferToVRAM();
00527         }
00528     }
00529 
00530     //
00531     // Return the pressed key
00532     //
00533     return KeyEvent;
00534 }
00535 #endif

Generated on Sun May 27 2012 04:19:18 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.