3 * Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31 BOOL
TuiDisplayMenu(PUCHAR MenuItemList
[], U32 MenuItemCount
, U32 DefaultMenuItem
, S32 MenuTimeOut
, U32
* SelectedMenuItem
, BOOL CanEscape
, UiMenuKeyPressFilterCallback KeyPressFilter
)
33 TUI_MENU_INFO MenuInformation
;
35 U32 CurrentClockSecond
;
39 // The first thing we need to check is the timeout
40 // If it's zero then don't bother with anything,
41 // just return the default item
45 if (SelectedMenuItem
!= NULL
)
47 *SelectedMenuItem
= DefaultMenuItem
;
54 // Setup the MENU_INFO structure
56 MenuInformation
.MenuItemList
= MenuItemList
;
57 MenuInformation
.MenuItemCount
= MenuItemCount
;
58 MenuInformation
.MenuTimeRemaining
= MenuTimeOut
;
59 MenuInformation
.SelectedMenuItem
= DefaultMenuItem
;
62 // Calculate the size of the menu box
64 TuiCalcMenuBoxSize(&MenuInformation
);
69 TuiDrawMenu(&MenuInformation
);
72 // Get the current second of time
74 MachRTCGetCurrentDateTime(NULL
, NULL
, NULL
, NULL
, NULL
, &LastClockSecond
);
82 // Process key presses
84 KeyPress
= TuiProcessMenuKeyboardEvent(&MenuInformation
, KeyPressFilter
);
85 if (KeyPress
== KEY_ENTER
)
88 // If they pressed enter then exit this loop
92 else if (CanEscape
&& KeyPress
== KEY_ESC
)
95 // They pressed escape, so just return FALSE
101 // Update the date & time
105 VideoCopyOffScreenBufferToVRAM();
107 if (MenuInformation
.MenuTimeRemaining
> 0)
109 MachRTCGetCurrentDateTime(NULL
, NULL
, NULL
, NULL
, NULL
, &CurrentClockSecond
);
110 if (CurrentClockSecond
!= LastClockSecond
)
113 // Update the time information
115 LastClockSecond
= CurrentClockSecond
;
116 MenuInformation
.MenuTimeRemaining
--;
121 TuiDrawMenuBox(&MenuInformation
);
123 VideoCopyOffScreenBufferToVRAM();
126 else if (MenuInformation
.MenuTimeRemaining
== 0)
129 // A time out occurred, exit this loop and return default OS
136 // Update the selected menu item information
138 if (SelectedMenuItem
!= NULL
)
140 *SelectedMenuItem
= MenuInformation
.SelectedMenuItem
;
146 VOID
TuiCalcMenuBoxSize(PTUI_MENU_INFO MenuInfo
)
154 // Height is the menu item count plus 2 (top border & bottom border)
156 Height
= MenuInfo
->MenuItemCount
+ 2;
157 Height
-= 1; // Height is zero-based
160 // Find the length of the longest string in the menu
163 for(Idx
=0; Idx
<MenuInfo
->MenuItemCount
; Idx
++)
165 Length
= strlen(MenuInfo
->MenuItemList
[Idx
]);
174 // Allow room for left & right borders, plus 8 spaces on each side
179 // Calculate the menu box area
181 MenuInfo
->Left
= (UiScreenWidth
- Width
) / 2;
182 MenuInfo
->Right
= (MenuInfo
->Left
) + Width
;
183 MenuInfo
->Top
= (((UiScreenHeight
- TUI_TITLE_BOX_CHAR_HEIGHT
) - Height
) / 2) + TUI_TITLE_BOX_CHAR_HEIGHT
;
184 MenuInfo
->Bottom
= (MenuInfo
->Top
) + Height
;
187 VOID
TuiDrawMenu(PTUI_MENU_INFO MenuInfo
)
197 // Update the status bar
199 UiDrawStatusText("Use \x18\x19 to select, then press ENTER.");
204 TuiDrawMenuBox(MenuInfo
);
207 // Draw each line of the menu
209 for (Idx
=0; Idx
<MenuInfo
->MenuItemCount
; Idx
++)
211 TuiDrawMenuItem(MenuInfo
, Idx
);
214 VideoCopyOffScreenBufferToVRAM();
217 VOID
TuiDrawMenuBox(PTUI_MENU_INFO MenuInfo
)
219 UCHAR MenuLineText
[80];
220 UCHAR TempString
[80];
226 UiDrawBox(MenuInfo
->Left
,
234 ATTR(UiMenuFgColor
, UiMenuBgColor
));
237 // If there is a timeout draw the time remaining
239 if (MenuInfo
->MenuTimeRemaining
>= 0)
241 strcpy(MenuLineText
, "[ Time Remaining: ");
242 itoa(MenuInfo
->MenuTimeRemaining
, TempString
, 10);
243 strcat(MenuLineText
, TempString
);
244 strcat(MenuLineText
, " ]");
246 UiDrawText(MenuInfo
->Right
- strlen(MenuLineText
) - 1,
249 ATTR(UiMenuFgColor
, UiMenuBgColor
));
253 // Now draw the separators
255 for (Idx
=0; Idx
<MenuInfo
->MenuItemCount
; Idx
++)
257 if (stricmp(MenuInfo
->MenuItemList
[Idx
], "SEPARATOR") == 0)
259 UiDrawText(MenuInfo
->Left
, MenuInfo
->Top
+ Idx
+ 1, "\xC7", ATTR(UiMenuFgColor
, UiMenuBgColor
));
260 UiDrawText(MenuInfo
->Right
, MenuInfo
->Top
+ Idx
+ 1, "\xB6", ATTR(UiMenuFgColor
, UiMenuBgColor
));
265 VOID
TuiDrawMenuItem(PTUI_MENU_INFO MenuInfo
, U32 MenuItemNumber
)
268 UCHAR MenuLineText
[80];
275 // We will want the string centered so calculate
276 // how many spaces will be to the left and right
278 SpaceTotal
= (MenuInfo
->Right
- MenuInfo
->Left
- 2) - strlen(MenuInfo
->MenuItemList
[MenuItemNumber
]);
279 SpaceLeft
= (SpaceTotal
/ 2) + 1;
280 SpaceRight
= (SpaceTotal
- SpaceLeft
) + 1;
283 // Insert the spaces on the left
285 for (Idx
=0; Idx
<SpaceLeft
; Idx
++)
287 MenuLineText
[Idx
] = ' ';
289 MenuLineText
[Idx
] = '\0';
292 // Now append the text string
294 strcat(MenuLineText
, MenuInfo
->MenuItemList
[MenuItemNumber
]);
297 // Now append the spaces on the right
299 for (Idx
=0; Idx
<SpaceRight
; Idx
++)
301 strcat(MenuLineText
, " ");
305 // If it is a separator then adjust the text accordingly
307 if (stricmp(MenuInfo
->MenuItemList
[MenuItemNumber
], "SEPARATOR") == 0)
309 memset(MenuLineText
, 0, 80);
310 memset(MenuLineText
, 0xC4, (MenuInfo
->Right
- MenuInfo
->Left
- 1));
311 Attribute
= ATTR(UiMenuFgColor
, UiMenuBgColor
);
315 Attribute
= ATTR(UiTextColor
, UiMenuBgColor
);
319 // If this is the selected menu item then draw it as selected
320 // otherwise just draw it using the normal colors
322 if (MenuItemNumber
== MenuInfo
->SelectedMenuItem
)
324 UiDrawText(MenuInfo
->Left
+ 1,
325 MenuInfo
->Top
+ 1 + MenuItemNumber
,
327 ATTR(UiSelectedTextColor
, UiSelectedTextBgColor
));
331 UiDrawText(MenuInfo
->Left
+ 1,
332 MenuInfo
->Top
+ 1 + MenuItemNumber
,
338 U32
TuiProcessMenuKeyboardEvent(PTUI_MENU_INFO MenuInfo
, UiMenuKeyPressFilterCallback KeyPressFilter
)
343 // Check for a keypress
348 // Cancel the timeout
350 if (MenuInfo
->MenuTimeRemaining
!= -1)
352 MenuInfo
->MenuTimeRemaining
= -1;
353 TuiDrawMenuBox(MenuInfo
);
359 KeyEvent
= MachConsGetCh();
365 KeyEvent
= MachConsGetCh(); // Yes - so get the extended key
368 // Call the supplied key filter callback function to see
369 // if it is going to handle this keypress.
371 if (KeyPressFilter
!= NULL
)
373 if (KeyPressFilter(KeyEvent
))
375 // It processed the key character
376 TuiDrawMenu(MenuInfo
);
389 if (MenuInfo
->SelectedMenuItem
> 0)
391 MenuInfo
->SelectedMenuItem
--;
396 TuiDrawMenuItem(MenuInfo
, MenuInfo
->SelectedMenuItem
+ 1); // Deselect previous item
398 // Skip past any separators
399 if (MenuInfo
->SelectedMenuItem
> 0 && stricmp(MenuInfo
->MenuItemList
[MenuInfo
->SelectedMenuItem
], "SEPARATOR") == 0)
401 MenuInfo
->SelectedMenuItem
--;
404 TuiDrawMenuItem(MenuInfo
, MenuInfo
->SelectedMenuItem
); // Select new item
411 if (MenuInfo
->SelectedMenuItem
< (MenuInfo
->MenuItemCount
- 1))
413 MenuInfo
->SelectedMenuItem
++;
418 TuiDrawMenuItem(MenuInfo
, MenuInfo
->SelectedMenuItem
- 1); // Deselect previous item
420 // Skip past any separators
421 if (MenuInfo
->SelectedMenuItem
< (MenuInfo
->MenuItemCount
- 1) && stricmp(MenuInfo
->MenuItemList
[MenuInfo
->SelectedMenuItem
], "SEPARATOR") == 0)
423 MenuInfo
->SelectedMenuItem
++;
426 TuiDrawMenuItem(MenuInfo
, MenuInfo
->SelectedMenuItem
); // Select new item
432 VideoCopyOffScreenBufferToVRAM();