Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentuimenu.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
1.7.6.1
|