menu.4th revision 254108
1222417Sjulian\ Copyright (c) 2003 Scott Long <scottl@freebsd.org> 2222417Sjulian\ Copyright (c) 2003 Aleksander Fafula <alex@fafula.com> 3254105Sdteske\ Copyright (c) 2006-2013 Devin Teske <dteske@FreeBSD.org> 4222417Sjulian\ All rights reserved. 5222417Sjulian\ 6222417Sjulian\ Redistribution and use in source and binary forms, with or without 7222417Sjulian\ modification, are permitted provided that the following conditions 8222417Sjulian\ are met: 9222417Sjulian\ 1. Redistributions of source code must retain the above copyright 10222417Sjulian\ notice, this list of conditions and the following disclaimer. 11222417Sjulian\ 2. Redistributions in binary form must reproduce the above copyright 12222417Sjulian\ notice, this list of conditions and the following disclaimer in the 13222417Sjulian\ documentation and/or other materials provided with the distribution. 14222417Sjulian\ 15222417Sjulian\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16222417Sjulian\ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17222417Sjulian\ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18222417Sjulian\ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19222417Sjulian\ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20222417Sjulian\ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21222417Sjulian\ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22222417Sjulian\ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23222417Sjulian\ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24222417Sjulian\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25222417Sjulian\ SUCH DAMAGE. 26222417Sjulian\ 27222417Sjulian\ $FreeBSD: head/sys/boot/forth/menu.4th 254108 2013-08-08 22:34:00Z dteske $ 28222417Sjulian 29222417Sjulianmarker task-menu.4th 30222417Sjulian 31222417Sjulian\ Frame drawing 32222417Sjulianinclude /boot/frames.4th 33222417Sjulian 34222417Sjulianf_double \ Set frames to double (see frames.4th). Replace with 35222417Sjulian \ f_single if you want single frames. 36222417Sjulian46 constant dot \ ASCII definition of a period (in decimal) 37222417Sjulian 38254108Sdteske 5 constant menu_default_x \ default column position of timeout 39254108Sdteske10 constant menu_default_y \ default row position of timeout msg 40222417Sjulian 4 constant menu_timeout_default_x \ default column position of timeout 41222417Sjulian23 constant menu_timeout_default_y \ default row position of timeout msg 42222417Sjulian10 constant menu_timeout_default \ default timeout (in seconds) 43222417Sjulian 44222417Sjulian\ Customize the following values with care 45222417Sjulian 46222417Sjulian 1 constant menu_start \ Numerical prefix of first menu item 47222417Sjuliandot constant bullet \ Menu bullet (appears after numerical prefix) 48222417Sjulian 5 constant menu_x \ Row position of the menu (from the top) 49222417Sjulian 10 constant menu_y \ Column position of the menu (from left side) 50222417Sjulian 51222417Sjulian\ Menu Appearance 52222417Sjulianvariable menuidx \ Menu item stack for number prefixes 53222417Sjulianvariable menurow \ Menu item stack for positioning 54222417Sjulianvariable menubllt \ Menu item bullet 55222417Sjulian 56222417Sjulian\ Menu Positioning 57222417Sjulianvariable menuX \ Menu X offset (columns) 58222417Sjulianvariable menuY \ Menu Y offset (rows) 59222417Sjulian 60222417Sjulian\ Menu-item key association/detection 61222417Sjulianvariable menukey1 62222417Sjulianvariable menukey2 63222417Sjulianvariable menukey3 64222417Sjulianvariable menukey4 65222417Sjulianvariable menukey5 66222417Sjulianvariable menukey6 67222417Sjulianvariable menukey7 68222417Sjulianvariable menukey8 69222417Sjulianvariable menureboot 70222417Sjulianvariable menurebootadded 71222417Sjulianvariable menuacpi 72222417Sjulianvariable menuoptions 73222417Sjulian 74222417Sjulian\ Menu timer [count-down] variables 75222417Sjulianvariable menu_timeout_enabled \ timeout state (internal use only) 76222417Sjulianvariable menu_time \ variable for tracking the passage of time 77222417Sjulianvariable menu_timeout \ determined configurable delay duration 78222417Sjulianvariable menu_timeout_x \ column position of timeout message 79222417Sjulianvariable menu_timeout_y \ row position of timeout message 80222417Sjulian 81241523Sdteske\ Menu initialization status variables 82241523Sdteskevariable init_state1 83241523Sdteskevariable init_state2 84241523Sdteskevariable init_state3 85241523Sdteskevariable init_state4 86241523Sdteskevariable init_state5 87241523Sdteskevariable init_state6 88241523Sdteskevariable init_state7 89241523Sdteskevariable init_state8 90241523Sdteske 91222417Sjulian\ Boolean option status variables 92222417Sjulianvariable toggle_state1 93222417Sjulianvariable toggle_state2 94222417Sjulianvariable toggle_state3 95222417Sjulianvariable toggle_state4 96222417Sjulianvariable toggle_state5 97222417Sjulianvariable toggle_state6 98222417Sjulianvariable toggle_state7 99222417Sjulianvariable toggle_state8 100222417Sjulian 101222417Sjulian\ Array option status variables 102222417Sjulianvariable cycle_state1 103222417Sjulianvariable cycle_state2 104222417Sjulianvariable cycle_state3 105222417Sjulianvariable cycle_state4 106222417Sjulianvariable cycle_state5 107222417Sjulianvariable cycle_state6 108222417Sjulianvariable cycle_state7 109222417Sjulianvariable cycle_state8 110222417Sjulian 111222417Sjulian\ Containers for storing the initial caption text 112222417Sjuliancreate init_text1 255 allot 113222417Sjuliancreate init_text2 255 allot 114222417Sjuliancreate init_text3 255 allot 115222417Sjuliancreate init_text4 255 allot 116222417Sjuliancreate init_text5 255 allot 117222417Sjuliancreate init_text6 255 allot 118222417Sjuliancreate init_text7 255 allot 119222417Sjuliancreate init_text8 255 allot 120222417Sjulian 121243114Sdteske: +c! ( N C-ADDR/U K -- C-ADDR/U ) 122243114Sdteske 3 pick 3 pick ( n c-addr/u k -- n c-addr/u k n c-addr ) 123243114Sdteske rot + c! ( n c-addr/u k n c-addr -- n c-addr/u ) 124243114Sdteske rot drop ( n c-addr/u -- c-addr/u ) 125243114Sdteske; 126243114Sdteske 127243114Sdteske: menukeyN ( N -- ADDR ) s" menukeyN" 7 +c! evaluate ; 128243114Sdteske: init_stateN ( N -- ADDR ) s" init_stateN" 10 +c! evaluate ; 129243114Sdteske: toggle_stateN ( N -- ADDR ) s" toggle_stateN" 12 +c! evaluate ; 130243114Sdteske: cycle_stateN ( N -- ADDR ) s" cycle_stateN" 11 +c! evaluate ; 131243114Sdteske: init_textN ( N -- C-ADDR ) s" init_textN" 9 +c! evaluate ; 132243114Sdteske 133254108Sdteske: str_loader_menu_frame ( -- C-ADDR/U ) s" loader_menu_frame" ; 134254108Sdteske: str_loader_menu_title ( -- C-ADDR/U ) s" loader_menu_title" ; 135254108Sdteske: str_loader_menu_title_align ( -- C-ADDR/U ) s" loader_menu_title_align" ; 136254108Sdteske: str_loader_menu_x ( -- C-ADDR/U ) s" loader_menu_x" ; 137254108Sdteske: str_loader_menu_y ( -- C-ADDR/U ) s" loader_menu_y" ; 138254108Sdteske: str_loader_menu_timeout_x ( -- C-ADDR/U ) s" loader_menu_timeout_x" ; 139254108Sdteske: str_loader_menu_timeout_y ( -- C-ADDR/U ) s" loader_menu_timeout_y" ; 140254108Sdteske: str_menu_init ( -- C-ADDR/U ) s" menu_init" ; 141254108Sdteske: str_menu_timeout_command ( -- C-ADDR/U ) s" menu_timeout_command" ; 142254108Sdteske: str_menu_reboot ( -- C-ADDR/U ) s" menu_reboot" ; 143254108Sdteske: str_menu_acpi ( -- C-ADDR/U ) s" menu_acpi" ; 144254108Sdteske: str_menu_options ( -- C-ADDR/U ) s" menu_options" ; 145254108Sdteske: str_menu_optionstext ( -- C-ADDR/U ) s" menu_optionstext" ; 146243114Sdteske 147243114Sdteske: str_menu_init[x] ( -- C-ADDR/U ) s" menu_init[x]" ; 148243114Sdteske: str_menu_command[x] ( -- C-ADDR/U ) s" menu_command[x]" ; 149243114Sdteske: str_menu_caption[x] ( -- C-ADDR/U ) s" menu_caption[x]" ; 150243114Sdteske: str_ansi_caption[x] ( -- C-ADDR/U ) s" ansi_caption[x]" ; 151243114Sdteske: str_menu_keycode[x] ( -- C-ADDR/U ) s" menu_keycode[x]" ; 152243114Sdteske: str_toggled_text[x] ( -- C-ADDR/U ) s" toggled_text[x]" ; 153243114Sdteske: str_toggled_ansi[x] ( -- C-ADDR/U ) s" toggled_ansi[x]" ; 154243114Sdteske: str_menu_caption[x][y] ( -- C-ADDR/U ) s" menu_caption[x][y]" ; 155243114Sdteske: str_ansi_caption[x][y] ( -- C-ADDR/U ) s" ansi_caption[x][y]" ; 156243114Sdteske 157243114Sdteske: menu_init[x] ( N -- C-ADDR/U ) str_menu_init[x] 10 +c! ; 158243114Sdteske: menu_command[x] ( N -- C-ADDR/U ) str_menu_command[x] 13 +c! ; 159243114Sdteske: menu_caption[x] ( N -- C-ADDR/U ) str_menu_caption[x] 13 +c! ; 160243114Sdteske: ansi_caption[x] ( N -- C-ADDR/U ) str_ansi_caption[x] 13 +c! ; 161243114Sdteske: menu_keycode[x] ( N -- C-ADDR/U ) str_menu_keycode[x] 13 +c! ; 162243114Sdteske: toggled_text[x] ( N -- C-ADDR/U ) str_toggled_text[x] 13 +c! ; 163243114Sdteske: toggled_ansi[x] ( N -- C-ADDR/U ) str_toggled_ansi[x] 13 +c! ; 164243114Sdteske: menu_caption[x][y] ( N M -- C-ADDR/U ) str_menu_caption[x][y] 16 +c! 13 +c! ; 165243114Sdteske: ansi_caption[x][y] ( N M -- C-ADDR/U ) str_ansi_caption[x][y] 16 +c! 13 +c! ; 166243114Sdteske 167222417Sjulian: arch-i386? ( -- BOOL ) \ Returns TRUE (-1) on i386, FALSE (0) otherwise. 168222417Sjulian s" arch-i386" environment? dup if 169222417Sjulian drop 170222417Sjulian then 171222417Sjulian; 172222417Sjulian 173222417Sjulian\ This function prints a menu item at menuX (row) and menuY (column), returns 174222417Sjulian\ the incremental decimal ASCII value associated with the menu item, and 175222417Sjulian\ increments the cursor position to the next row for the creation of the next 176222417Sjulian\ menu item. This function is called by the menu-create function. You need not 177222417Sjulian\ call it directly. 178222417Sjulian\ 179222417Sjulian: printmenuitem ( menu_item_str -- ascii_keycode ) 180222417Sjulian 181222417Sjulian menurow dup @ 1+ swap ! ( increment menurow ) 182222417Sjulian menuidx dup @ 1+ swap ! ( increment menuidx ) 183222417Sjulian 184222417Sjulian \ Calculate the menuitem row position 185222417Sjulian menurow @ menuY @ + 186222417Sjulian 187222417Sjulian \ Position the cursor at the menuitem position 188222417Sjulian dup menuX @ swap at-xy 189222417Sjulian 190222417Sjulian \ Print the value of menuidx 191222417Sjulian loader_color? if 192228985Spluknet ." [1m" ( [22m ) 193222417Sjulian then 194222417Sjulian menuidx @ . 195222417Sjulian loader_color? if 196228985Spluknet ." [37m" ( [39m ) 197222417Sjulian then 198222417Sjulian 199222417Sjulian \ Move the cursor forward 1 column 200222417Sjulian dup menuX @ 1+ swap at-xy 201222417Sjulian 202222417Sjulian menubllt @ emit \ Print the menu bullet using the emit function 203222417Sjulian 204222417Sjulian \ Move the cursor to the 3rd column from the current position 205222417Sjulian \ to allow for a space between the numerical prefix and the 206222417Sjulian \ text caption 207222417Sjulian menuX @ 3 + swap at-xy 208222417Sjulian 209222417Sjulian \ Print the menu caption (we expect a string to be on the stack 210222417Sjulian \ prior to invoking this function) 211222417Sjulian type 212222417Sjulian 213222417Sjulian \ Here we will add the ASCII decimal of the numerical prefix 214222417Sjulian \ to the stack (decimal ASCII for `1' is 49) as a "return value" 215222417Sjulian menuidx @ 48 + 216222417Sjulian; 217222417Sjulian 218222417Sjulian: toggle_menuitem ( N -- N ) \ toggles caption text and internal menuitem state 219222417Sjulian 220222417Sjulian \ ASCII numeral equal to user-selected menu item must be on the stack. 221222417Sjulian \ We do not modify the stack, so the ASCII numeral is left on top. 222222417Sjulian 223243114Sdteske dup init_textN c@ 0= if 224222417Sjulian \ NOTE: no need to check toggle_stateN since the first time we 225222417Sjulian \ are called, we will populate init_textN. Further, we don't 226222417Sjulian \ need to test whether menu_caption[x] (ansi_caption[x] when 227254105Sdteske \ loader_color?=1) is available since we would not have been 228222417Sjulian \ called if the caption was NULL. 229222417Sjulian 230222417Sjulian \ base name of environment variable 231243114Sdteske dup ( n -- n n ) \ key pressed 232222417Sjulian loader_color? if 233243114Sdteske ansi_caption[x] 234222417Sjulian else 235243114Sdteske menu_caption[x] 236222417Sjulian then 237222417Sjulian getenv dup -1 <> if 238222417Sjulian 239243114Sdteske 2 pick ( n c-addr/u -- n c-addr/u n ) 240243114Sdteske init_textN ( n c-addr/u n -- n c-addr/u c-addr ) 241222417Sjulian 242222417Sjulian \ now we have the buffer c-addr on top 243222417Sjulian \ ( followed by c-addr/u of current caption ) 244222417Sjulian 245222417Sjulian \ Copy the current caption into our buffer 246222417Sjulian 2dup c! -rot \ store strlen at first byte 247222417Sjulian begin 248222417Sjulian rot 1+ \ bring alt addr to top and increment 249222417Sjulian -rot -rot \ bring buffer addr to top 250222417Sjulian 2dup c@ swap c! \ copy current character 251222417Sjulian 1+ \ increment buffer addr 252222417Sjulian rot 1- \ bring buffer len to top and decrement 253222417Sjulian dup 0= \ exit loop if buffer len is zero 254222417Sjulian until 255222417Sjulian 2drop \ buffer len/addr 256222417Sjulian drop \ alt addr 257222417Sjulian 258222417Sjulian else 259222417Sjulian drop 260222417Sjulian then 261222417Sjulian then 262222417Sjulian 263222417Sjulian \ Now we are certain to have init_textN populated with the initial 264222417Sjulian \ value of menu_caption[x] (ansi_caption[x] with loader_color enabled). 265222417Sjulian \ We can now use init_textN as the untoggled caption and 266222417Sjulian \ toggled_text[x] (toggled_ansi[x] with loader_color enabled) as the 267222417Sjulian \ toggled caption and store the appropriate value into menu_caption[x] 268222417Sjulian \ (again, ansi_caption[x] with loader_color enabled). Last, we'll 269222417Sjulian \ negate the toggled state so that we reverse the flow on subsequent 270222417Sjulian \ calls. 271222417Sjulian 272243114Sdteske dup toggle_stateN @ 0= if 273222417Sjulian \ state is OFF, toggle to ON 274222417Sjulian 275243114Sdteske dup ( n -- n n ) \ key pressed 276222417Sjulian loader_color? if 277243114Sdteske toggled_ansi[x] 278222417Sjulian else 279243114Sdteske toggled_text[x] 280222417Sjulian then 281222417Sjulian getenv dup -1 <> if 282222417Sjulian \ Assign toggled text to menu caption 283243114Sdteske 2 pick ( n c-addr/u -- n c-addr/u n ) \ key pressed 284222417Sjulian loader_color? if 285243114Sdteske ansi_caption[x] 286222417Sjulian else 287243114Sdteske menu_caption[x] 288222417Sjulian then 289243114Sdteske setenv 290222417Sjulian else 291222417Sjulian \ No toggled text, keep the same caption 292243114Sdteske drop ( n -1 -- n ) \ getenv cruft 293222417Sjulian then 294222417Sjulian 295222417Sjulian true \ new value of toggle state var (to be stored later) 296222417Sjulian else 297222417Sjulian \ state is ON, toggle to OFF 298222417Sjulian 299243114Sdteske dup init_textN count ( n -- n c-addr/u ) 300222417Sjulian 301243114Sdteske \ Assign init_textN text to menu caption 302243114Sdteske 2 pick ( n c-addr/u -- n c-addr/u n ) \ key pressed 303222417Sjulian loader_color? if 304243114Sdteske ansi_caption[x] 305222417Sjulian else 306243114Sdteske menu_caption[x] 307222417Sjulian then 308243114Sdteske setenv 309222417Sjulian 310243114Sdteske false \ new value of toggle state var (to be stored below) 311222417Sjulian then 312222417Sjulian 313222417Sjulian \ now we'll store the new toggle state (on top of stack) 314243114Sdteske over toggle_stateN ! 315222417Sjulian; 316222417Sjulian 317222417Sjulian: cycle_menuitem ( N -- N ) \ cycles through array of choices for a menuitem 318222417Sjulian 319222417Sjulian \ ASCII numeral equal to user-selected menu item must be on the stack. 320222417Sjulian \ We do not modify the stack, so the ASCII numeral is left on top. 321222417Sjulian 322243114Sdteske dup cycle_stateN dup @ 1+ \ get value and increment 323222417Sjulian 324222417Sjulian \ Before assigning the (incremented) value back to the pointer, 325222417Sjulian \ let's test for the existence of this particular array element. 326222417Sjulian \ If the element exists, we'll store index value and move on. 327222417Sjulian \ Otherwise, we'll loop around to zero and store that. 328222417Sjulian 329243114Sdteske dup 48 + ( n addr k -- n addr k k' ) 330243114Sdteske \ duplicate array index and convert to ASCII numeral 331222417Sjulian 332243114Sdteske 3 pick swap ( n addr k k' -- n addr k n k' ) \ (n,k') as (x,y) 333222417Sjulian loader_color? if 334243114Sdteske ansi_caption[x][y] 335222417Sjulian else 336243114Sdteske menu_caption[x][y] 337222417Sjulian then 338243114Sdteske ( n addr k n k' -- n addr k c-addr/u ) 339222417Sjulian 340222417Sjulian \ Now test for the existence of our incremented array index in the 341222417Sjulian \ form of $menu_caption[x][y] ($ansi_caption[x][y] with loader_color 342222417Sjulian \ enabled) as set in loader.rc(5), et. al. 343222417Sjulian 344222417Sjulian getenv dup -1 = if 345222417Sjulian \ No caption set for this array index. Loop back to zero. 346222417Sjulian 347243114Sdteske drop ( n addr k -1 -- n addr k ) \ getenv cruft 348243114Sdteske drop 0 ( n addr k -- n addr 0 ) \ new value to store later 349222417Sjulian 350243114Sdteske 2 pick [char] 0 ( n addr 0 -- n addr 0 n 48 ) \ (n,48) as (x,y) 351222417Sjulian loader_color? if 352243114Sdteske ansi_caption[x][y] 353222417Sjulian else 354243114Sdteske menu_caption[x][y] 355222417Sjulian then 356243114Sdteske ( n addr 0 n 48 -- n addr 0 c-addr/u ) 357222417Sjulian getenv dup -1 = if 358222417Sjulian \ This is highly unlikely to occur, but to make 359222417Sjulian \ sure that things move along smoothly, allocate 360222417Sjulian \ a temporary NULL string 361222417Sjulian 362243114Sdteske drop ( n addr 0 -1 -- n addr 0 ) \ getenv cruft 363243114Sdteske s" " ( n addr 0 -- n addr 0 c-addr/u ) 364222417Sjulian then 365222417Sjulian then 366222417Sjulian 367222417Sjulian \ At this point, we should have the following on the stack (in order, 368222417Sjulian \ from bottom to top): 369222417Sjulian \ 370243114Sdteske \ n - Ascii numeral representing the menu choice (inherited) 371243114Sdteske \ addr - address of our internal cycle_stateN variable 372243114Sdteske \ k - zero-based number we intend to store to the above 373243114Sdteske \ c-addr/u - string value we intend to store to menu_caption[x] 374243114Sdteske \ (or ansi_caption[x] with loader_color enabled) 375222417Sjulian \ 376222417Sjulian \ Let's perform what we need to with the above. 377222417Sjulian 378243114Sdteske \ Assign array value text to menu caption 379243114Sdteske 4 pick ( n addr k c-addr/u -- n addr k c-addr/u n ) 380222417Sjulian loader_color? if 381243114Sdteske ansi_caption[x] 382222417Sjulian else 383243114Sdteske menu_caption[x] 384222417Sjulian then 385243114Sdteske setenv 386222417Sjulian 387243114Sdteske swap ! ( n addr k -- n ) \ update array state variable 388222417Sjulian; 389222417Sjulian 390222417Sjulian: acpipresent? ( -- flag ) \ Returns TRUE if ACPI is present, FALSE otherwise 391222417Sjulian s" hint.acpi.0.rsdp" getenv 392222417Sjulian dup -1 = if 393222417Sjulian drop false exit 394222417Sjulian then 395222417Sjulian 2drop 396222417Sjulian true 397222417Sjulian; 398222417Sjulian 399222417Sjulian: acpienabled? ( -- flag ) \ Returns TRUE if ACPI is enabled, FALSE otherwise 400222417Sjulian s" hint.acpi.0.disabled" getenv 401222417Sjulian dup -1 <> if 402222417Sjulian s" 0" compare 0<> if 403222417Sjulian false exit 404222417Sjulian then 405222417Sjulian else 406222417Sjulian drop 407222417Sjulian then 408222417Sjulian true 409222417Sjulian; 410222417Sjulian 411222417Sjulian\ This function prints the appropriate menuitem basename to the stack if an 412222417Sjulian\ ACPI option is to be presented to the user, otherwise returns -1. Used 413222417Sjulian\ internally by menu-create, you need not (nor should you) call this directly. 414222417Sjulian\ 415241310Sdteske: acpimenuitem ( -- C-Addr/U | -1 ) 416222417Sjulian 417222417Sjulian arch-i386? if 418222417Sjulian acpipresent? if 419222417Sjulian acpienabled? if 420222417Sjulian loader_color? if 421243114Sdteske str_toggled_ansi[x] 422222417Sjulian else 423243114Sdteske str_toggled_text[x] 424222417Sjulian then 425222417Sjulian else 426222417Sjulian loader_color? if 427243114Sdteske str_ansi_caption[x] 428222417Sjulian else 429243114Sdteske str_menu_caption[x] 430222417Sjulian then 431222417Sjulian then 432222417Sjulian else 433222417Sjulian menuidx dup @ 1+ swap ! ( increment menuidx ) 434222417Sjulian -1 435222417Sjulian then 436222417Sjulian else 437222417Sjulian -1 438222417Sjulian then 439222417Sjulian; 440222417Sjulian 441222417Sjulian\ This function creates the list of menu items. This function is called by the 442222417Sjulian\ menu-display function. You need not be call it directly. 443222417Sjulian\ 444222417Sjulian: menu-create ( -- ) 445222417Sjulian 446222417Sjulian \ Print the frame caption at (x,y) 447243114Sdteske str_loader_menu_title getenv dup -1 = if 448222417Sjulian drop s" Welcome to FreeBSD" 449222417Sjulian then 450254108Sdteske TRUE ( use default alignment ) 451254108Sdteske str_loader_menu_title_align getenv dup -1 <> if 452254108Sdteske 2dup s" left" compare-insensitive 0= if ( 1 ) 453254108Sdteske 2drop ( c-addr/u ) drop ( bool ) 454254108Sdteske menuX @ menuY @ 1- 455254108Sdteske FALSE ( don't use default alignment ) 456254108Sdteske else ( 1 ) 2dup s" right" compare-insensitive 0= if ( 2 ) 457254108Sdteske 2drop ( c-addr/u ) drop ( bool ) 458254108Sdteske menuX @ 42 + 4 - over - menuY @ 1- 459254108Sdteske FALSE ( don't use default alignment ) 460254108Sdteske else ( 2 ) 2drop ( c-addr/u ) then ( 1 ) then 461254108Sdteske else 462254108Sdteske drop ( getenv cruft ) 463254108Sdteske then 464254108Sdteske if ( use default center alignement? ) 465254108Sdteske menuX @ 19 + over 2 / - menuY @ 1- 466254108Sdteske then 467254108Sdteske at-xy type 468222417Sjulian 469241523Sdteske \ If $menu_init is set, evaluate it (allowing for whole menus to be 470241523Sdteske \ constructed dynamically -- as this function could conceivably set 471241523Sdteske \ the remaining environment variables to construct the menu entirely). 472241523Sdteske \ 473243114Sdteske str_menu_init getenv dup -1 <> if 474241523Sdteske evaluate 475241523Sdteske else 476241523Sdteske drop 477241523Sdteske then 478241523Sdteske 479222417Sjulian \ Print our menu options with respective key/variable associations. 480222417Sjulian \ `printmenuitem' ends by adding the decimal ASCII value for the 481222417Sjulian \ numerical prefix to the stack. We store the value left on the stack 482222417Sjulian \ to the key binding variable for later testing against a character 483222417Sjulian \ captured by the `getkey' function. 484222417Sjulian 485222417Sjulian \ Note that any menu item beyond 9 will have a numerical prefix on the 486222417Sjulian \ screen consisting of the first digit (ie. 1 for the tenth menu item) 487222417Sjulian \ and the key required to activate that menu item will be the decimal 488222417Sjulian \ ASCII of 48 plus the menu item (ie. 58 for the tenth item, aka. `:') 489222417Sjulian \ which is misleading and not desirable. 490222417Sjulian \ 491222417Sjulian \ Thus, we do not allow more than 8 configurable items on the menu 492222417Sjulian \ (with "Reboot" as the optional ninth and highest numbered item). 493222417Sjulian 494222417Sjulian \ 495222417Sjulian \ Initialize the ACPI option status. 496222417Sjulian \ 497222417Sjulian 0 menuacpi ! 498243114Sdteske str_menu_acpi getenv -1 <> if 499222417Sjulian c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' ) 500222417Sjulian menuacpi ! 501222417Sjulian arch-i386? if acpipresent? if 502222417Sjulian \ 503222417Sjulian \ Set menu toggle state to active state 504222417Sjulian \ (required by generic toggle_menuitem) 505222417Sjulian \ 506243114Sdteske acpienabled? menuacpi @ toggle_stateN ! 507222417Sjulian then then 508222417Sjulian else 509222417Sjulian drop 510222417Sjulian then 511222417Sjulian then 512222417Sjulian 513222417Sjulian \ 514222417Sjulian \ Initialize the menu_options visual separator. 515222417Sjulian \ 516222417Sjulian 0 menuoptions ! 517243114Sdteske str_menu_options getenv -1 <> if 518222417Sjulian c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' ) 519222417Sjulian menuoptions ! 520222417Sjulian else 521222417Sjulian drop 522222417Sjulian then 523222417Sjulian then 524222417Sjulian 525222417Sjulian \ Initialize "Reboot" menu state variable (prevents double-entry) 526222417Sjulian false menurebootadded ! 527222417Sjulian 528242667Sdteske menu_start 529242667Sdteske 1- menuidx ! \ Initialize the starting index for the menu 530242667Sdteske 0 menurow ! \ Initialize the starting position for the menu 531242667Sdteske 532222417Sjulian 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8') 533222417Sjulian begin 534222417Sjulian \ If the "Options:" separator, print it. 535222417Sjulian dup menuoptions @ = if 536222417Sjulian \ Optionally add a reboot option to the menu 537243114Sdteske str_menu_reboot getenv -1 <> if 538222417Sjulian drop 539222417Sjulian s" Reboot" printmenuitem menureboot ! 540222417Sjulian true menurebootadded ! 541222417Sjulian then 542222417Sjulian 543222417Sjulian menuX @ 544222417Sjulian menurow @ 2 + menurow ! 545222417Sjulian menurow @ menuY @ + 546222417Sjulian at-xy 547243114Sdteske str_menu_optionstext getenv dup -1 <> if 548241363Sdteske type 549241363Sdteske else 550241363Sdteske drop ." Options:" 551241363Sdteske then 552222417Sjulian then 553222417Sjulian 554222417Sjulian \ If this is the ACPI menu option, act accordingly. 555222417Sjulian dup menuacpi @ = if 556243114Sdteske dup acpimenuitem ( n -- n n c-addr/u | n n -1 ) 557243114Sdteske dup -1 <> if 558243114Sdteske 13 +c! ( n n c-addr/u -- n c-addr/u ) 559243114Sdteske \ replace 'x' with n 560243114Sdteske else 561243114Sdteske swap drop ( n n -1 -- n -1 ) 562243114Sdteske over menu_command[x] unsetenv 563243114Sdteske then 564222417Sjulian else 565241523Sdteske \ make sure we have not already initialized this item 566243114Sdteske dup init_stateN dup @ 0= if 567241523Sdteske 1 swap ! 568241523Sdteske 569241523Sdteske \ If this menuitem has an initializer, run it 570243114Sdteske dup menu_init[x] 571241523Sdteske getenv dup -1 <> if 572241523Sdteske evaluate 573241523Sdteske else 574241523Sdteske drop 575241523Sdteske then 576241523Sdteske else 577241523Sdteske drop 578241523Sdteske then 579241523Sdteske 580243114Sdteske dup 581222417Sjulian loader_color? if 582243114Sdteske ansi_caption[x] 583222417Sjulian else 584243114Sdteske menu_caption[x] 585222417Sjulian then 586222417Sjulian then 587222417Sjulian 588222417Sjulian dup -1 <> if 589222417Sjulian \ test for environment variable 590222417Sjulian getenv dup -1 <> if 591243114Sdteske printmenuitem ( c-addr/u -- n ) 592243114Sdteske dup menukeyN ! 593222417Sjulian else 594222417Sjulian drop 595222417Sjulian then 596222417Sjulian else 597222417Sjulian drop 598222417Sjulian then 599222417Sjulian 600222417Sjulian 1+ dup 56 > \ add 1 to iterator, continue if less than 57 601222417Sjulian until 602222417Sjulian drop \ iterator 603222417Sjulian 604222417Sjulian \ Optionally add a reboot option to the menu 605222417Sjulian menurebootadded @ true <> if 606243114Sdteske str_menu_reboot getenv -1 <> if 607222417Sjulian drop \ no need for the value 608222417Sjulian s" Reboot" \ menu caption (required by printmenuitem) 609222417Sjulian 610222417Sjulian printmenuitem 611222417Sjulian menureboot ! 612222417Sjulian else 613222417Sjulian 0 menureboot ! 614222417Sjulian then 615222417Sjulian then 616222417Sjulian; 617222417Sjulian 618222417Sjulian\ Takes a single integer on the stack and updates the timeout display. The 619222417Sjulian\ integer must be between 0 and 9 (we will only update a single digit in the 620222417Sjulian\ source message). 621222417Sjulian\ 622222417Sjulian: menu-timeout-update ( N -- ) 623222417Sjulian 624243114Sdteske \ Enforce minimum/maximum 625243114Sdteske dup 9 > if drop 9 then 626243114Sdteske dup 0 < if drop 0 then 627222417Sjulian 628243114Sdteske s" Autoboot in N seconds. [Space] to pause" ( n -- n c-addr/u ) 629222417Sjulian 630243114Sdteske 2 pick 0> if 631243114Sdteske rot 48 + -rot ( n c-addr/u -- n' c-addr/u ) \ convert to ASCII 632243114Sdteske 12 +c! ( n' c-addr/u -- c-addr/u ) \ replace 'N' above 633222417Sjulian 634243114Sdteske menu_timeout_x @ menu_timeout_y @ at-xy \ position cursor 635243114Sdteske type ( c-addr/u -- ) \ print message 636243114Sdteske else 637243114Sdteske menu_timeout_x @ menu_timeout_y @ at-xy \ position cursor 638243114Sdteske spaces ( n c-addr/u -- n c-addr ) \ erase message 639243114Sdteske 2drop ( n c-addr -- ) 640222417Sjulian then 641222417Sjulian 642222417Sjulian 0 25 at-xy ( position cursor back at bottom-left ) 643222417Sjulian; 644222417Sjulian 645222417Sjulian\ This function blocks program flow (loops forever) until a key is pressed. 646222417Sjulian\ The key that was pressed is added to the top of the stack in the form of its 647222417Sjulian\ decimal ASCII representation. This function is called by the menu-display 648222417Sjulian\ function. You need not call it directly. 649222417Sjulian\ 650222417Sjulian: getkey ( -- ascii_keycode ) 651222417Sjulian 652222417Sjulian begin \ loop forever 653222417Sjulian 654222417Sjulian menu_timeout_enabled @ 1 = if 655222417Sjulian ( -- ) 656222417Sjulian seconds ( get current time: -- N ) 657222417Sjulian dup menu_time @ <> if ( has time elapsed?: N N N -- N ) 658222417Sjulian 659222417Sjulian \ At least 1 second has elapsed since last loop 660222417Sjulian \ so we will decrement our "timeout" (really a 661222417Sjulian \ counter, insuring that we do not proceed too 662222417Sjulian \ fast) and update our timeout display. 663222417Sjulian 664222417Sjulian menu_time ! ( update time record: N -- ) 665222417Sjulian menu_timeout @ ( "time" remaining: -- N ) 666222417Sjulian dup 0> if ( greater than 0?: N N 0 -- N ) 667222417Sjulian 1- ( decrement counter: N -- N ) 668222417Sjulian dup menu_timeout ! 669222417Sjulian ( re-assign: N N Addr -- N ) 670222417Sjulian then 671222417Sjulian ( -- N ) 672222417Sjulian 673222417Sjulian dup 0= swap 0< or if ( N <= 0?: N N -- ) 674222417Sjulian \ halt the timer 675222417Sjulian 0 menu_timeout ! ( 0 Addr -- ) 676222417Sjulian 0 menu_timeout_enabled ! ( 0 Addr -- ) 677222417Sjulian then 678222417Sjulian 679222417Sjulian \ update the timer display ( N -- ) 680222417Sjulian menu_timeout @ menu-timeout-update 681222417Sjulian 682222417Sjulian menu_timeout @ 0= if 683222417Sjulian \ We've reached the end of the timeout 684222417Sjulian \ (user did not cancel by pressing ANY 685222417Sjulian \ key) 686222417Sjulian 687243114Sdteske str_menu_timeout_command getenv dup 688222417Sjulian -1 = if 689222417Sjulian drop \ clean-up 690222417Sjulian else 691222417Sjulian evaluate 692222417Sjulian then 693222417Sjulian then 694222417Sjulian 695222417Sjulian else ( -- N ) 696222417Sjulian \ No [detectable] time has elapsed (in seconds) 697222417Sjulian drop ( N -- ) 698222417Sjulian then 699222417Sjulian ( -- ) 700222417Sjulian then 701222417Sjulian 702222417Sjulian key? if \ Was a key pressed? (see loader(8)) 703222417Sjulian 704222417Sjulian \ An actual key was pressed (if the timeout is running, 705222417Sjulian \ kill it regardless of which key was pressed) 706222417Sjulian menu_timeout @ 0<> if 707222417Sjulian 0 menu_timeout ! 708222417Sjulian 0 menu_timeout_enabled ! 709222417Sjulian 710222417Sjulian \ clear screen of timeout message 711222417Sjulian 0 menu-timeout-update 712222417Sjulian then 713222417Sjulian 714222417Sjulian \ get the key that was pressed and exit (if we 715222417Sjulian \ get a non-zero ASCII code) 716222417Sjulian key dup 0<> if 717222417Sjulian exit 718222417Sjulian else 719222417Sjulian drop 720222417Sjulian then 721222417Sjulian then 722222417Sjulian 50 ms \ sleep for 50 milliseconds (see loader(8)) 723222417Sjulian 724222417Sjulian again 725222417Sjulian; 726222417Sjulian 727222417Sjulian: menu-erase ( -- ) \ Erases menu and resets positioning variable to positon 1. 728222417Sjulian 729222417Sjulian \ Clear the screen area associated with the interactive menu 730222417Sjulian menuX @ menuY @ 731222417Sjulian 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+ 732222417Sjulian 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+ 733222417Sjulian 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+ 734222417Sjulian 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+ 735222417Sjulian 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+ 736222417Sjulian 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 737222417Sjulian 2drop 738222417Sjulian 739222417Sjulian \ Reset the starting index and position for the menu 740222417Sjulian menu_start 1- menuidx ! 741222417Sjulian 0 menurow ! 742222417Sjulian; 743222417Sjulian 744222417Sjulian\ Erase and redraw the menu. Useful if you change a caption and want to 745222417Sjulian\ update the menu to reflect the new value. 746222417Sjulian\ 747222417Sjulian: menu-redraw ( -- ) 748222417Sjulian menu-erase 749222417Sjulian menu-create 750222417Sjulian; 751222417Sjulian 752222417Sjulian\ This function initializes the menu. Call this from your `loader.rc' file 753222417Sjulian\ before calling any other menu-related functions. 754222417Sjulian\ 755222417Sjulian: menu-init ( -- ) 756222417Sjulian menu_start 757222417Sjulian 1- menuidx ! \ Initialize the starting index for the menu 758222417Sjulian 0 menurow ! \ Initialize the starting position for the menu 759254108Sdteske 760254108Sdteske \ Assign configuration values 761254108Sdteske str_loader_menu_y getenv dup -1 = if 762254108Sdteske drop \ no custom row position 763254108Sdteske menu_default_y 764254108Sdteske else 765254108Sdteske \ make sure custom position is a number 766254108Sdteske ?number 0= if 767254108Sdteske menu_default_y \ or use default 768254108Sdteske then 769254108Sdteske then 770254108Sdteske menuY ! 771254108Sdteske str_loader_menu_x getenv dup -1 = if 772254108Sdteske drop \ no custom column position 773254108Sdteske menu_default_x 774254108Sdteske else 775254108Sdteske \ make sure custom position is a number 776254108Sdteske ?number 0= if 777254108Sdteske menu_default_x \ or use default 778254108Sdteske then 779254108Sdteske then 780254108Sdteske menuX ! 781254108Sdteske 782254108Sdteske \ Interpret a custom frame type for the menu 783254108Sdteske TRUE ( draw a box? default yes, but might be altered below ) 784254108Sdteske str_loader_menu_frame getenv dup -1 = if ( 1 ) 785254108Sdteske drop \ no custom frame type 786254108Sdteske else ( 1 ) 2dup s" single" compare-insensitive 0= if ( 2 ) 787254108Sdteske f_single ( see frames.4th ) 788254108Sdteske else ( 2 ) 2dup s" double" compare-insensitive 0= if ( 3 ) 789254108Sdteske f_double ( see frames.4th ) 790254108Sdteske else ( 3 ) s" none" compare-insensitive 0= if ( 4 ) 791254108Sdteske drop FALSE \ don't draw a box 792254108Sdteske ( 4 ) then ( 3 ) then ( 2 ) then ( 1 ) then 793254108Sdteske if 794254108Sdteske 42 13 menuX @ 3 - menuY @ 1- box \ Draw frame (w,h,x,y) 795254108Sdteske then 796254108Sdteske 797254108Sdteske 0 25 at-xy \ Move cursor to the bottom for output 798222417Sjulian; 799222417Sjulian 800222417Sjulian\ Main function. Call this from your `loader.rc' file. 801222417Sjulian\ 802222417Sjulian: menu-display ( -- ) 803222417Sjulian 804222417Sjulian 0 menu_timeout_enabled ! \ start with automatic timeout disabled 805222417Sjulian 806222417Sjulian \ check indication that automatic execution after delay is requested 807243114Sdteske str_menu_timeout_command getenv -1 <> if ( Addr C -1 -- | Addr ) 808222417Sjulian drop ( just testing existence right now: Addr -- ) 809222417Sjulian 810222417Sjulian \ initialize state variables 811222417Sjulian seconds menu_time ! ( store the time we started ) 812222417Sjulian 1 menu_timeout_enabled ! ( enable automatic timeout ) 813222417Sjulian 814222417Sjulian \ read custom time-duration (if set) 815222417Sjulian s" autoboot_delay" getenv dup -1 = if 816222417Sjulian drop \ no custom duration (remove dup'd bunk -1) 817222417Sjulian menu_timeout_default \ use default setting 818222417Sjulian else 819222417Sjulian 2dup ?number 0= if ( if not a number ) 820222417Sjulian \ disable timeout if "NO", else use default 821222417Sjulian s" NO" compare-insensitive 0= if 822222417Sjulian 0 menu_timeout_enabled ! 823222417Sjulian 0 ( assigned to menu_timeout below ) 824222417Sjulian else 825222417Sjulian menu_timeout_default 826222417Sjulian then 827222417Sjulian else 828222417Sjulian -rot 2drop 829222417Sjulian 830225353Sjh \ boot immediately if less than zero 831222417Sjulian dup 0< if 832222417Sjulian drop 833225353Sjh menu-create 834225353Sjh 0 25 at-xy 835225353Sjh 0 boot 836222417Sjulian then 837222417Sjulian then 838222417Sjulian then 839222417Sjulian menu_timeout ! ( store value on stack from above ) 840222417Sjulian 841222417Sjulian menu_timeout_enabled @ 1 = if 842222417Sjulian \ read custom column position (if set) 843243114Sdteske str_loader_menu_timeout_x getenv dup -1 = if 844222417Sjulian drop \ no custom column position 845222417Sjulian menu_timeout_default_x \ use default setting 846222417Sjulian else 847222417Sjulian \ make sure custom position is a number 848222417Sjulian ?number 0= if 849222417Sjulian menu_timeout_default_x \ or use default 850222417Sjulian then 851222417Sjulian then 852222417Sjulian menu_timeout_x ! ( store value on stack from above ) 853222417Sjulian 854222417Sjulian \ read custom row position (if set) 855243114Sdteske str_loader_menu_timeout_y getenv dup -1 = if 856222417Sjulian drop \ no custom row position 857222417Sjulian menu_timeout_default_y \ use default setting 858222417Sjulian else 859222417Sjulian \ make sure custom position is a number 860222417Sjulian ?number 0= if 861222417Sjulian menu_timeout_default_y \ or use default 862222417Sjulian then 863222417Sjulian then 864222417Sjulian menu_timeout_y ! ( store value on stack from above ) 865222417Sjulian then 866222417Sjulian then 867222417Sjulian 868222417Sjulian menu-create 869222417Sjulian 870222417Sjulian begin \ Loop forever 871222417Sjulian 872222417Sjulian 0 25 at-xy \ Move cursor to the bottom for output 873222417Sjulian getkey \ Block here, waiting for a key to be pressed 874222417Sjulian 875222417Sjulian dup -1 = if 876222417Sjulian drop exit \ Caught abort (abnormal return) 877222417Sjulian then 878222417Sjulian 879222417Sjulian \ Boot if the user pressed Enter/Ctrl-M (13) or 880222417Sjulian \ Ctrl-Enter/Ctrl-J (10) 881222417Sjulian dup over 13 = swap 10 = or if 882222417Sjulian drop ( no longer needed ) 883222417Sjulian s" boot" evaluate 884222417Sjulian exit ( pedantic; never reached ) 885222417Sjulian then 886222417Sjulian 887242667Sdteske dup menureboot @ = if 0 reboot then 888242667Sdteske 889222417Sjulian \ Evaluate the decimal ASCII value against known menu item 890222417Sjulian \ key associations and act accordingly 891222417Sjulian 892222417Sjulian 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8') 893222417Sjulian begin 894243114Sdteske dup menukeyN @ 895243114Sdteske rot tuck = if 896222417Sjulian 897222417Sjulian \ Adjust for missing ACPI menuitem on non-i386 898222417Sjulian arch-i386? true <> menuacpi @ 0<> and if 899222417Sjulian menuacpi @ over 2dup < -rot = or 900222417Sjulian over 58 < and if 901222417Sjulian ( key >= menuacpi && key < 58: N -- N ) 902222417Sjulian 1+ 903222417Sjulian then 904222417Sjulian then 905222417Sjulian 906222417Sjulian \ Test for the environment variable 907243114Sdteske dup menu_command[x] 908222417Sjulian getenv dup -1 <> if 909222417Sjulian \ Execute the stored procedure 910222417Sjulian evaluate 911222417Sjulian 912222417Sjulian \ We expect there to be a non-zero 913222417Sjulian \ value left on the stack after 914222417Sjulian \ executing the stored procedure. 915222417Sjulian \ If so, continue to run, else exit. 916222417Sjulian 917222417Sjulian 0= if 918222417Sjulian drop \ key pressed 919222417Sjulian drop \ loop iterator 920222417Sjulian exit 921222417Sjulian else 922222417Sjulian swap \ need iterator on top 923222417Sjulian then 924222417Sjulian then 925222417Sjulian 926222417Sjulian \ Re-adjust for missing ACPI menuitem 927222417Sjulian arch-i386? true <> menuacpi @ 0<> and if 928222417Sjulian swap 929222417Sjulian menuacpi @ 1+ over 2dup < -rot = or 930222417Sjulian over 59 < and if 931222417Sjulian 1- 932222417Sjulian then 933222417Sjulian swap 934222417Sjulian then 935222417Sjulian else 936222417Sjulian swap \ need iterator on top 937222417Sjulian then 938222417Sjulian 939222417Sjulian \ 940222417Sjulian \ Check for menu keycode shortcut(s) 941222417Sjulian \ 942243114Sdteske dup menu_keycode[x] 943222417Sjulian getenv dup -1 = if 944222417Sjulian drop 945222417Sjulian else 946222417Sjulian ?number 0<> if 947222417Sjulian rot tuck = if 948222417Sjulian swap 949243114Sdteske dup menu_command[x] 950222417Sjulian getenv dup -1 <> if 951222417Sjulian evaluate 952222417Sjulian 0= if 953222417Sjulian 2drop 954222417Sjulian exit 955222417Sjulian then 956222417Sjulian else 957222417Sjulian drop 958222417Sjulian then 959222417Sjulian else 960222417Sjulian swap 961222417Sjulian then 962222417Sjulian then 963222417Sjulian then 964222417Sjulian 965222417Sjulian 1+ dup 56 > \ increment iterator 966222417Sjulian \ continue if less than 57 967222417Sjulian until 968222417Sjulian drop \ loop iterator 969242667Sdteske drop \ key pressed 970222417Sjulian 971222417Sjulian again \ Non-operational key was pressed; repeat 972222417Sjulian; 973222417Sjulian 974222417Sjulian\ This function unsets all the possible environment variables associated with 975228985Spluknet\ creating the interactive menu. 976222417Sjulian\ 977228985Spluknet: menu-unset ( -- ) 978222417Sjulian 979222417Sjulian 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8') 980222417Sjulian begin 981243114Sdteske dup menu_init[x] unsetenv \ menu initializer 982243114Sdteske dup menu_command[x] unsetenv \ menu command 983243114Sdteske dup menu_caption[x] unsetenv \ menu caption 984243114Sdteske dup ansi_caption[x] unsetenv \ ANSI caption 985243114Sdteske dup menu_keycode[x] unsetenv \ menu keycode 986243114Sdteske dup toggled_text[x] unsetenv \ toggle_menuitem caption 987243114Sdteske dup toggled_ansi[x] unsetenv \ toggle_menuitem ANSI caption 988228985Spluknet 989243114Sdteske 48 \ Iterator start (inner range 48 to 57; ASCII '0' to '9') 990228985Spluknet begin 991243114Sdteske \ cycle_menuitem caption and ANSI caption 992243114Sdteske 2dup menu_caption[x][y] unsetenv 993243114Sdteske 2dup ansi_caption[x][y] unsetenv 994243114Sdteske 1+ dup 57 > 995228985Spluknet until 996243114Sdteske drop \ inner iterator 997228985Spluknet 998243114Sdteske 0 over menukeyN ! \ used by menu-create, menu-display 999243114Sdteske 0 over init_stateN ! \ used by menu-create 1000243114Sdteske 0 over toggle_stateN ! \ used by toggle_menuitem 1001243114Sdteske 0 over init_textN c! \ used by toggle_menuitem 1002243114Sdteske 0 over cycle_stateN ! \ used by cycle_menuitem 1003228985Spluknet 1004222417Sjulian 1+ dup 56 > \ increment, continue if less than 57 1005222417Sjulian until 1006222417Sjulian drop \ iterator 1007222417Sjulian 1008243114Sdteske str_menu_timeout_command unsetenv \ menu timeout command 1009243114Sdteske str_menu_reboot unsetenv \ Reboot menu option flag 1010243114Sdteske str_menu_acpi unsetenv \ ACPI menu option flag 1011243114Sdteske str_menu_options unsetenv \ Options separator flag 1012243114Sdteske str_menu_optionstext unsetenv \ separator display text 1013243114Sdteske str_menu_init unsetenv \ menu initializer 1014228985Spluknet 1015222417Sjulian 0 menureboot ! 1016222417Sjulian 0 menuacpi ! 1017222417Sjulian 0 menuoptions ! 1018228985Spluknet; 1019228985Spluknet 1020228985Spluknet\ This function both unsets menu variables and visually erases the menu area 1021228985Spluknet\ in-preparation for another menu. 1022228985Spluknet\ 1023228985Spluknet: menu-clear ( -- ) 1024228985Spluknet menu-unset 1025222417Sjulian menu-erase 1026222417Sjulian; 1027222417Sjulian 1028222417Sjulianbullet menubllt ! 1029222417Sjulian 1030241523Sdteske\ Initialize our menu initialization state variables 1031241523Sdteske0 init_state1 ! 1032241523Sdteske0 init_state2 ! 1033241523Sdteske0 init_state3 ! 1034241523Sdteske0 init_state4 ! 1035241523Sdteske0 init_state5 ! 1036241523Sdteske0 init_state6 ! 1037241523Sdteske0 init_state7 ! 1038241523Sdteske0 init_state8 ! 1039241523Sdteske 1040222417Sjulian\ Initialize our boolean state variables 1041222417Sjulian0 toggle_state1 ! 1042222417Sjulian0 toggle_state2 ! 1043222417Sjulian0 toggle_state3 ! 1044222417Sjulian0 toggle_state4 ! 1045222417Sjulian0 toggle_state5 ! 1046222417Sjulian0 toggle_state6 ! 1047222417Sjulian0 toggle_state7 ! 1048222417Sjulian0 toggle_state8 ! 1049222417Sjulian 1050222417Sjulian\ Initialize our array state variables 1051222417Sjulian0 cycle_state1 ! 1052222417Sjulian0 cycle_state2 ! 1053222417Sjulian0 cycle_state3 ! 1054222417Sjulian0 cycle_state4 ! 1055222417Sjulian0 cycle_state5 ! 1056222417Sjulian0 cycle_state6 ! 1057222417Sjulian0 cycle_state7 ! 1058222417Sjulian0 cycle_state8 ! 1059222417Sjulian 1060222417Sjulian\ Initialize string containers 1061222417Sjulian0 init_text1 c! 1062222417Sjulian0 init_text2 c! 1063222417Sjulian0 init_text3 c! 1064222417Sjulian0 init_text4 c! 1065222417Sjulian0 init_text5 c! 1066222417Sjulian0 init_text6 c! 1067222417Sjulian0 init_text7 c! 1068222417Sjulian0 init_text8 c! 1069