1ca987d46SWarner Losh\ Copyright (c) 2003 Scott Long <scottl@FreeBSD.org> 2ca987d46SWarner Losh\ Copyright (c) 2003 Aleksander Fafula <alex@fafula.com> 3ca987d46SWarner Losh\ Copyright (c) 2006-2015 Devin Teske <dteske@FreeBSD.org> 4ca987d46SWarner Losh\ All rights reserved. 5ca987d46SWarner Losh\ 6ca987d46SWarner Losh\ Redistribution and use in source and binary forms, with or without 7ca987d46SWarner Losh\ modification, are permitted provided that the following conditions 8ca987d46SWarner Losh\ are met: 9ca987d46SWarner Losh\ 1. Redistributions of source code must retain the above copyright 10ca987d46SWarner Losh\ notice, this list of conditions and the following disclaimer. 11ca987d46SWarner Losh\ 2. Redistributions in binary form must reproduce the above copyright 12ca987d46SWarner Losh\ notice, this list of conditions and the following disclaimer in the 13ca987d46SWarner Losh\ documentation and/or other materials provided with the distribution. 14ca987d46SWarner Losh\ 15ca987d46SWarner Losh\ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16ca987d46SWarner Losh\ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17ca987d46SWarner Losh\ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18ca987d46SWarner Losh\ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19ca987d46SWarner Losh\ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20ca987d46SWarner Losh\ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21ca987d46SWarner Losh\ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22ca987d46SWarner Losh\ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23ca987d46SWarner Losh\ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24ca987d46SWarner Losh\ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25ca987d46SWarner Losh\ SUCH DAMAGE. 26ca987d46SWarner Losh\ 27ca987d46SWarner Losh 28ca987d46SWarner Loshmarker task-menu.4th 29ca987d46SWarner Losh 30ca987d46SWarner Losh\ Frame drawing 31ca987d46SWarner Loshinclude /boot/frames.4th 32ca987d46SWarner Losh 33ca987d46SWarner Loshvocabulary menu-infrastructure 34ca987d46SWarner Loshvocabulary menu-namespace 35ca987d46SWarner Loshvocabulary menu-command-helpers 36ca987d46SWarner Losh 37ca987d46SWarner Loshonly forth also menu-infrastructure definitions 38ca987d46SWarner Losh 39ca987d46SWarner Loshf_double \ Set frames to double (see frames.4th). Replace with 40ca987d46SWarner Losh \ f_single if you want single frames. 41ca987d46SWarner Losh46 constant dot \ ASCII definition of a period (in decimal) 42ca987d46SWarner Losh 43ca987d46SWarner Losh 5 constant menu_default_x \ default column position of timeout 44ca987d46SWarner Losh10 constant menu_default_y \ default row position of timeout msg 45ca987d46SWarner Losh 4 constant menu_timeout_default_x \ default column position of timeout 46ca987d46SWarner Losh23 constant menu_timeout_default_y \ default row position of timeout msg 47ca987d46SWarner Losh10 constant menu_timeout_default \ default timeout (in seconds) 48ca987d46SWarner Losh 49ca987d46SWarner Losh\ Customize the following values with care 50ca987d46SWarner Losh 51ca987d46SWarner Losh 1 constant menu_start \ Numerical prefix of first menu item 52ca987d46SWarner Loshdot constant bullet \ Menu bullet (appears after numerical prefix) 53ca987d46SWarner Losh 5 constant menu_x \ Row position of the menu (from the top) 54ca987d46SWarner Losh 10 constant menu_y \ Column position of the menu (from left side) 55ca987d46SWarner Losh 56ca987d46SWarner Losh\ Menu Appearance 57ca987d46SWarner Loshvariable menuidx \ Menu item stack for number prefixes 58ca987d46SWarner Loshvariable menurow \ Menu item stack for positioning 59ca987d46SWarner Loshvariable menubllt \ Menu item bullet 60ca987d46SWarner Losh 61ca987d46SWarner Losh\ Menu Positioning 62ca987d46SWarner Loshvariable menuX \ Menu X offset (columns) 63ca987d46SWarner Loshvariable menuY \ Menu Y offset (rows) 64ca987d46SWarner Losh 65ca987d46SWarner Losh\ Menu-item elements 66ca987d46SWarner Loshvariable menurebootadded 67ca987d46SWarner Losh 68ca987d46SWarner Losh\ Parsing of kernels into menu-items 69ca987d46SWarner Loshvariable kernidx 70ca987d46SWarner Loshvariable kernlen 71ca987d46SWarner Loshvariable kernmenuidx 72ca987d46SWarner Losh 73ca987d46SWarner Losh\ Menu timer [count-down] variables 74ca987d46SWarner Loshvariable menu_timeout_enabled \ timeout state (internal use only) 75ca987d46SWarner Loshvariable menu_time \ variable for tracking the passage of time 76ca987d46SWarner Loshvariable menu_timeout \ determined configurable delay duration 77ca987d46SWarner Loshvariable menu_timeout_x \ column position of timeout message 78ca987d46SWarner Loshvariable menu_timeout_y \ row position of timeout message 79ca987d46SWarner Losh 80ca987d46SWarner Losh\ Containers for parsing kernels into menu-items 81ca987d46SWarner Loshcreate kerncapbuf 64 allot 82ca987d46SWarner Loshcreate kerndefault 64 allot 83ca987d46SWarner Loshcreate kernelsbuf 256 allot 84ca987d46SWarner Losh 85ca987d46SWarner Loshonly forth also menu-namespace definitions 86ca987d46SWarner Losh 87ca987d46SWarner Losh\ Menu-item key association/detection 88ca987d46SWarner Loshvariable menukey1 89ca987d46SWarner Loshvariable menukey2 90ca987d46SWarner Loshvariable menukey3 91ca987d46SWarner Loshvariable menukey4 92ca987d46SWarner Loshvariable menukey5 93ca987d46SWarner Loshvariable menukey6 94ca987d46SWarner Loshvariable menukey7 95ca987d46SWarner Loshvariable menukey8 96ca987d46SWarner Loshvariable menureboot 97ca987d46SWarner Loshvariable menuacpi 98ca987d46SWarner Loshvariable menuoptions 99ca987d46SWarner Loshvariable menukernel 100ca987d46SWarner Losh 101ca987d46SWarner Losh\ Menu initialization status variables 102ca987d46SWarner Loshvariable init_state1 103ca987d46SWarner Loshvariable init_state2 104ca987d46SWarner Loshvariable init_state3 105ca987d46SWarner Loshvariable init_state4 106ca987d46SWarner Loshvariable init_state5 107ca987d46SWarner Loshvariable init_state6 108ca987d46SWarner Loshvariable init_state7 109ca987d46SWarner Loshvariable init_state8 110ca987d46SWarner Losh 111ca987d46SWarner Losh\ Boolean option status variables 112ca987d46SWarner Loshvariable toggle_state1 113ca987d46SWarner Loshvariable toggle_state2 114ca987d46SWarner Loshvariable toggle_state3 115ca987d46SWarner Loshvariable toggle_state4 116ca987d46SWarner Loshvariable toggle_state5 117ca987d46SWarner Loshvariable toggle_state6 118ca987d46SWarner Loshvariable toggle_state7 119ca987d46SWarner Loshvariable toggle_state8 120ca987d46SWarner Losh 121ca987d46SWarner Losh\ Array option status variables 122ca987d46SWarner Loshvariable cycle_state1 123ca987d46SWarner Loshvariable cycle_state2 124ca987d46SWarner Loshvariable cycle_state3 125ca987d46SWarner Loshvariable cycle_state4 126ca987d46SWarner Loshvariable cycle_state5 127ca987d46SWarner Loshvariable cycle_state6 128ca987d46SWarner Loshvariable cycle_state7 129ca987d46SWarner Loshvariable cycle_state8 130ca987d46SWarner Losh 131ca987d46SWarner Losh\ Containers for storing the initial caption text 132ca987d46SWarner Loshcreate init_text1 64 allot 133ca987d46SWarner Loshcreate init_text2 64 allot 134ca987d46SWarner Loshcreate init_text3 64 allot 135ca987d46SWarner Loshcreate init_text4 64 allot 136ca987d46SWarner Loshcreate init_text5 64 allot 137ca987d46SWarner Loshcreate init_text6 64 allot 138ca987d46SWarner Loshcreate init_text7 64 allot 139ca987d46SWarner Loshcreate init_text8 64 allot 140ca987d46SWarner Losh 141ca987d46SWarner Loshonly forth definitions 142ca987d46SWarner Losh 143ca987d46SWarner Losh: arch-i386? ( -- BOOL ) \ Returns TRUE (-1) on i386, FALSE (0) otherwise. 144ca987d46SWarner Losh s" arch-i386" environment? dup if 145ca987d46SWarner Losh drop 146ca987d46SWarner Losh then 147ca987d46SWarner Losh; 148ca987d46SWarner Losh 149ca987d46SWarner Losh: acpipresent? ( -- flag ) \ Returns TRUE if ACPI is present, FALSE otherwise 150*37798b1dSWarner Losh s" acpi.rsdp" getenv 151ca987d46SWarner Losh dup -1 = if 152ca987d46SWarner Losh drop false exit 153ca987d46SWarner Losh then 154ca987d46SWarner Losh 2drop 155ca987d46SWarner Losh true 156ca987d46SWarner Losh; 157ca987d46SWarner Losh 158ca987d46SWarner Losh: acpienabled? ( -- flag ) \ Returns TRUE if ACPI is enabled, FALSE otherwise 159ca987d46SWarner Losh s" hint.acpi.0.disabled" getenv 160ca987d46SWarner Losh dup -1 <> if 161ca987d46SWarner Losh s" 0" compare 0<> if 162ca987d46SWarner Losh false exit 163ca987d46SWarner Losh then 164ca987d46SWarner Losh else 165ca987d46SWarner Losh drop 166ca987d46SWarner Losh then 167ca987d46SWarner Losh true 168ca987d46SWarner Losh; 169ca987d46SWarner Losh 170ca987d46SWarner Losh: +c! ( N C-ADDR/U K -- C-ADDR/U ) 171ca987d46SWarner Losh 3 pick 3 pick ( n c-addr/u k -- n c-addr/u k n c-addr ) 172ca987d46SWarner Losh rot + c! ( n c-addr/u k n c-addr -- n c-addr/u ) 173ca987d46SWarner Losh rot drop ( n c-addr/u -- c-addr/u ) 174ca987d46SWarner Losh; 175ca987d46SWarner Losh 176ca987d46SWarner Loshonly forth also menu-namespace definitions 177ca987d46SWarner Losh 178ca987d46SWarner Losh\ Forth variables 179ca987d46SWarner Losh: namespace ( C-ADDR/U N -- ) also menu-namespace +c! evaluate previous ; 180ca987d46SWarner Losh: menukeyN ( N -- ADDR ) s" menukeyN" 7 namespace ; 181ca987d46SWarner Losh: init_stateN ( N -- ADDR ) s" init_stateN" 10 namespace ; 182ca987d46SWarner Losh: toggle_stateN ( N -- ADDR ) s" toggle_stateN" 12 namespace ; 183ca987d46SWarner Losh: cycle_stateN ( N -- ADDR ) s" cycle_stateN" 11 namespace ; 184ca987d46SWarner Losh: init_textN ( N -- C-ADDR ) s" init_textN" 9 namespace ; 185ca987d46SWarner Losh 186ca987d46SWarner Losh\ Environment variables 187ca987d46SWarner Losh: kernel[x] ( N -- C-ADDR/U ) s" kernel[x]" 7 +c! ; 188ca987d46SWarner Losh: menu_init[x] ( N -- C-ADDR/U ) s" menu_init[x]" 10 +c! ; 189ca987d46SWarner Losh: menu_command[x] ( N -- C-ADDR/U ) s" menu_command[x]" 13 +c! ; 190ca987d46SWarner Losh: menu_caption[x] ( N -- C-ADDR/U ) s" menu_caption[x]" 13 +c! ; 191ca987d46SWarner Losh: ansi_caption[x] ( N -- C-ADDR/U ) s" ansi_caption[x]" 13 +c! ; 192ca987d46SWarner Losh: menu_keycode[x] ( N -- C-ADDR/U ) s" menu_keycode[x]" 13 +c! ; 193ca987d46SWarner Losh: toggled_text[x] ( N -- C-ADDR/U ) s" toggled_text[x]" 13 +c! ; 194ca987d46SWarner Losh: toggled_ansi[x] ( N -- C-ADDR/U ) s" toggled_ansi[x]" 13 +c! ; 195ca987d46SWarner Losh: menu_caption[x][y] ( N M -- C-ADDR/U ) s" menu_caption[x][y]" 16 +c! 13 +c! ; 196ca987d46SWarner Losh: ansi_caption[x][y] ( N M -- C-ADDR/U ) s" ansi_caption[x][y]" 16 +c! 13 +c! ; 197ca987d46SWarner Losh 198ca987d46SWarner Loshalso menu-infrastructure definitions 199ca987d46SWarner Losh 200ca987d46SWarner Losh\ This function prints a menu item at menuX (row) and menuY (column), returns 201ca987d46SWarner Losh\ the incremental decimal ASCII value associated with the menu item, and 202ca987d46SWarner Losh\ increments the cursor position to the next row for the creation of the next 203ca987d46SWarner Losh\ menu item. This function is called by the menu-create function. You need not 204ca987d46SWarner Losh\ call it directly. 205ca987d46SWarner Losh\ 206ca987d46SWarner Losh: printmenuitem ( menu_item_str -- ascii_keycode ) 207ca987d46SWarner Losh 208ca987d46SWarner Losh loader_color? if [char] ^ escc! then 209ca987d46SWarner Losh 210ca987d46SWarner Losh menurow dup @ 1+ swap ! ( increment menurow ) 211ca987d46SWarner Losh menuidx dup @ 1+ swap ! ( increment menuidx ) 212ca987d46SWarner Losh 213ca987d46SWarner Losh \ Calculate the menuitem row position 214ca987d46SWarner Losh menurow @ menuY @ + 215ca987d46SWarner Losh 216ca987d46SWarner Losh \ Position the cursor at the menuitem position 217ca987d46SWarner Losh dup menuX @ swap at-xy 218ca987d46SWarner Losh 219ca987d46SWarner Losh \ Print the value of menuidx 220ca987d46SWarner Losh loader_color? dup ( -- bool bool ) 221ca987d46SWarner Losh if b then 222ca987d46SWarner Losh menuidx @ . 223ca987d46SWarner Losh if me then 224ca987d46SWarner Losh 225ca987d46SWarner Losh \ Move the cursor forward 1 column 226ca987d46SWarner Losh dup menuX @ 1+ swap at-xy 227ca987d46SWarner Losh 228ca987d46SWarner Losh menubllt @ emit \ Print the menu bullet using the emit function 229ca987d46SWarner Losh 230ca987d46SWarner Losh \ Move the cursor to the 3rd column from the current position 231ca987d46SWarner Losh \ to allow for a space between the numerical prefix and the 232ca987d46SWarner Losh \ text caption 233ca987d46SWarner Losh menuX @ 3 + swap at-xy 234ca987d46SWarner Losh 235ca987d46SWarner Losh \ Print the menu caption (we expect a string to be on the stack 236ca987d46SWarner Losh \ prior to invoking this function) 237ca987d46SWarner Losh type 238ca987d46SWarner Losh 239ca987d46SWarner Losh \ Here we will add the ASCII decimal of the numerical prefix 240ca987d46SWarner Losh \ to the stack (decimal ASCII for `1' is 49) as a "return value" 241ca987d46SWarner Losh menuidx @ 48 + 242ca987d46SWarner Losh; 243ca987d46SWarner Losh 244ca987d46SWarner Losh\ This function prints the appropriate menuitem basename to the stack if an 245ca987d46SWarner Losh\ ACPI option is to be presented to the user, otherwise returns -1. Used 246ca987d46SWarner Losh\ internally by menu-create, you need not (nor should you) call this directly. 247ca987d46SWarner Losh\ 248ca987d46SWarner Losh: acpimenuitem ( -- C-Addr/U | -1 ) 249ca987d46SWarner Losh 250ca987d46SWarner Losh arch-i386? if 251ca987d46SWarner Losh acpipresent? if 252ca987d46SWarner Losh acpienabled? if 253ca987d46SWarner Losh loader_color? if 254ca987d46SWarner Losh s" toggled_ansi[x]" 255ca987d46SWarner Losh else 256ca987d46SWarner Losh s" toggled_text[x]" 257ca987d46SWarner Losh then 258ca987d46SWarner Losh else 259ca987d46SWarner Losh loader_color? if 260ca987d46SWarner Losh s" ansi_caption[x]" 261ca987d46SWarner Losh else 262ca987d46SWarner Losh s" menu_caption[x]" 263ca987d46SWarner Losh then 264ca987d46SWarner Losh then 265ca987d46SWarner Losh else 266ca987d46SWarner Losh menuidx dup @ 1+ swap ! ( increment menuidx ) 267ca987d46SWarner Losh -1 268ca987d46SWarner Losh then 269ca987d46SWarner Losh else 270ca987d46SWarner Losh -1 271ca987d46SWarner Losh then 272ca987d46SWarner Losh; 273ca987d46SWarner Losh 274ca987d46SWarner Losh: delim? ( C -- BOOL ) 275ca987d46SWarner Losh dup 32 = ( c -- c bool ) \ [sp] space 276ca987d46SWarner Losh over 9 = or ( c bool -- c bool ) \ [ht] horizontal tab 277ca987d46SWarner Losh over 10 = or ( c bool -- c bool ) \ [nl] newline 278ca987d46SWarner Losh over 13 = or ( c bool -- c bool ) \ [cr] carriage return 279ca987d46SWarner Losh over [char] , = or ( c bool -- c bool ) \ comma 280ca987d46SWarner Losh swap drop ( c bool -- bool ) \ return boolean 281ca987d46SWarner Losh; 282ca987d46SWarner Losh 283ca987d46SWarner Losh\ This function parses $kernels into variables that are used by the menu to 284ca987d46SWarner Losh\ display which kernel to boot when the [overloaded] `boot' word is interpreted. 285ca987d46SWarner Losh\ Used internally by menu-create, you need not (nor should you) call this 286ca987d46SWarner Losh\ directly. 287ca987d46SWarner Losh\ 288ca987d46SWarner Losh: parse-kernels ( N -- ) \ kernidx 289ca987d46SWarner Losh kernidx ! ( n -- ) \ store provided `x' value 290ca987d46SWarner Losh [char] 0 kernmenuidx ! \ initialize `y' value for menu_caption[x][y] 291ca987d46SWarner Losh 292ca987d46SWarner Losh \ Attempt to get a list of kernels, fall back to sensible default 293ca987d46SWarner Losh s" kernels" getenv dup -1 = if 294ca987d46SWarner Losh drop ( cruft ) 295ca987d46SWarner Losh s" kernel kernel.old" 296ca987d46SWarner Losh then ( -- c-addr/u ) 297ca987d46SWarner Losh 298ca987d46SWarner Losh \ Check to see if the user has altered $kernel by comparing it against 299ca987d46SWarner Losh \ $kernel[N] where N is kernel_state (the actively displayed kernel). 300ca987d46SWarner Losh s" kernel_state" evaluate @ 48 + s" kernel[N]" 7 +c! getenv 301ca987d46SWarner Losh dup -1 <> if 302ca987d46SWarner Losh s" kernel" getenv dup -1 = if 303ca987d46SWarner Losh drop ( cruft ) s" " 304ca987d46SWarner Losh then 305ca987d46SWarner Losh 2swap 2over compare 0= if 306ca987d46SWarner Losh 2drop FALSE ( skip below conditional ) 307ca987d46SWarner Losh else \ User has changed $kernel 308ca987d46SWarner Losh TRUE ( slurp in new value ) 309ca987d46SWarner Losh then 310ca987d46SWarner Losh else \ We haven't yet parsed $kernels into $kernel[N] 311ca987d46SWarner Losh drop ( getenv cruft ) 312ca987d46SWarner Losh s" kernel" getenv dup -1 = if 313ca987d46SWarner Losh drop ( cruft ) s" " 314ca987d46SWarner Losh then 315ca987d46SWarner Losh TRUE ( slurp in initial value ) 316ca987d46SWarner Losh then ( c-addr/u -- c-addr/u c-addr/u,-1 | 0 ) 317ca987d46SWarner Losh if \ slurp new value into kerndefault 318ca987d46SWarner Losh kerndefault 1+ 0 2swap strcat swap 1- c! 319ca987d46SWarner Losh then 320ca987d46SWarner Losh 321ca987d46SWarner Losh \ Clear out existing parsed-kernels 322ca987d46SWarner Losh kernidx @ [char] 0 323ca987d46SWarner Losh begin 324ca987d46SWarner Losh dup kernel[x] unsetenv 325ca987d46SWarner Losh 2dup menu_caption[x][y] unsetenv 326ca987d46SWarner Losh 2dup ansi_caption[x][y] unsetenv 327ca987d46SWarner Losh 1+ dup [char] 8 > 328ca987d46SWarner Losh until 329ca987d46SWarner Losh 2drop 330ca987d46SWarner Losh 331ca987d46SWarner Losh \ Step through the string until we find the end 332ca987d46SWarner Losh begin 333ca987d46SWarner Losh 0 kernlen ! \ initialize length of value 334ca987d46SWarner Losh 335ca987d46SWarner Losh \ Skip leading whitespace and/or comma delimiters 336ca987d46SWarner Losh begin 337ca987d46SWarner Losh dup 0<> if 338ca987d46SWarner Losh over c@ delim? ( c-addr/u -- c-addr/u bool ) 339ca987d46SWarner Losh else 340ca987d46SWarner Losh false ( c-addr/u -- c-addr/u bool ) 341ca987d46SWarner Losh then 342ca987d46SWarner Losh while 343ca987d46SWarner Losh 1- swap 1+ swap ( c-addr/u -- c-addr'/u' ) 344ca987d46SWarner Losh repeat 345ca987d46SWarner Losh ( c-addr/u -- c-addr'/u' ) 346ca987d46SWarner Losh 347ca987d46SWarner Losh dup 0= if \ end of string while eating whitespace 348ca987d46SWarner Losh 2drop ( c-addr/u -- ) 349ca987d46SWarner Losh kernmenuidx @ [char] 0 <> if \ found at least one 350ca987d46SWarner Losh exit \ all done 351ca987d46SWarner Losh then 352ca987d46SWarner Losh 353ca987d46SWarner Losh \ No entries in $kernels; use $kernel instead 354ca987d46SWarner Losh s" kernel" getenv dup -1 = if 355ca987d46SWarner Losh drop ( cruft ) s" " 356ca987d46SWarner Losh then ( -- c-addr/u ) 357ca987d46SWarner Losh dup kernlen ! \ store entire value length as kernlen 358ca987d46SWarner Losh else 359ca987d46SWarner Losh \ We're still within $kernels parsing toward the end; 360ca987d46SWarner Losh \ find delimiter/end to determine kernlen 361ca987d46SWarner Losh 2dup ( c-addr/u -- c-addr/u c-addr/u ) 362ca987d46SWarner Losh begin dup 0<> while 363ca987d46SWarner Losh over c@ delim? if 364ca987d46SWarner Losh drop 0 ( break ) \ found delimiter 365ca987d46SWarner Losh else 366ca987d46SWarner Losh kernlen @ 1+ kernlen ! \ incrememnt 367ca987d46SWarner Losh 1- swap 1+ swap \ c-addr++ u-- 368ca987d46SWarner Losh then 369ca987d46SWarner Losh repeat 370ca987d46SWarner Losh 2drop ( c-addr/u c-addr'/u' -- c-addr/u ) 371ca987d46SWarner Losh 372ca987d46SWarner Losh \ If this is the first entry, compare it to $kernel 373ca987d46SWarner Losh \ If different, then insert $kernel beforehand 374ca987d46SWarner Losh kernmenuidx @ [char] 0 = if 375ca987d46SWarner Losh over kernlen @ kerndefault count compare if 376ca987d46SWarner Losh kernelsbuf 0 kerndefault count strcat 377ca987d46SWarner Losh s" ," strcat 2swap strcat 378ca987d46SWarner Losh kerndefault count swap drop kernlen ! 379ca987d46SWarner Losh then 380ca987d46SWarner Losh then 381ca987d46SWarner Losh then 382ca987d46SWarner Losh ( c-addr/u -- c-addr'/u' ) 383ca987d46SWarner Losh 384ca987d46SWarner Losh \ At this point, we should have something on the stack to store 385ca987d46SWarner Losh \ as the next kernel menu option; start assembling variables 386ca987d46SWarner Losh 387ca987d46SWarner Losh over kernlen @ ( c-addr/u -- c-addr/u c-addr/u2 ) 388ca987d46SWarner Losh 389ca987d46SWarner Losh \ Assign first to kernel[x] 390ca987d46SWarner Losh 2dup kernmenuidx @ kernel[x] setenv 391ca987d46SWarner Losh 392ca987d46SWarner Losh \ Assign second to menu_caption[x][y] 393ca987d46SWarner Losh kerncapbuf 0 s" [K]ernel: " strcat 394ca987d46SWarner Losh 2over strcat 395ca987d46SWarner Losh kernidx @ kernmenuidx @ menu_caption[x][y] 396ca987d46SWarner Losh setenv 397ca987d46SWarner Losh 398ca987d46SWarner Losh \ Assign third to ansi_caption[x][y] 3992de5a21eSToomas Soome kerncapbuf 0 s" @[1mK@[mernel: " [char] @ escc! strcat 400ca987d46SWarner Losh kernmenuidx @ [char] 0 = if 401ca987d46SWarner Losh s" default/@[32m" 402ca987d46SWarner Losh else 403ca987d46SWarner Losh s" @[34;1m" 404ca987d46SWarner Losh then 405ca987d46SWarner Losh [char] @ escc! strcat 406ca987d46SWarner Losh 2over strcat 4072de5a21eSToomas Soome s" @[m" [char] @ escc! strcat 408ca987d46SWarner Losh kernidx @ kernmenuidx @ ansi_caption[x][y] 409ca987d46SWarner Losh setenv 410ca987d46SWarner Losh 411ca987d46SWarner Losh 2drop ( c-addr/u c-addr/u2 -- c-addr/u ) 412ca987d46SWarner Losh 413ca987d46SWarner Losh kernmenuidx @ 1+ dup kernmenuidx ! [char] 8 > if 414ca987d46SWarner Losh 2drop ( c-addr/u -- ) exit 415ca987d46SWarner Losh then 416ca987d46SWarner Losh 417ca987d46SWarner Losh kernlen @ - swap kernlen @ + swap ( c-addr/u -- c-addr'/u' ) 418ca987d46SWarner Losh again 419ca987d46SWarner Losh; 420ca987d46SWarner Losh 421ca987d46SWarner Losh\ This function goes through the kernels that were discovered by the 422ca987d46SWarner Losh\ parse-kernels function [above], adding " (# of #)" text to the end of each 423ca987d46SWarner Losh\ caption. 424ca987d46SWarner Losh\ 425ca987d46SWarner Losh: tag-kernels ( -- ) 426ca987d46SWarner Losh kernidx @ ( -- x ) dup 0= if exit then 427ca987d46SWarner Losh [char] 0 s" (Y of Z)" ( x -- x y c-addr/u ) 428ca987d46SWarner Losh kernmenuidx @ -rot 7 +c! \ Replace 'Z' with number of kernels parsed 429ca987d46SWarner Losh begin 430ca987d46SWarner Losh 2 pick 1+ -rot 2 +c! \ Replace 'Y' with current ASCII num 431ca987d46SWarner Losh 432ca987d46SWarner Losh 2over menu_caption[x][y] getenv dup -1 <> if 433ca987d46SWarner Losh 2dup + 1- c@ [char] ) = if 434ca987d46SWarner Losh 2drop \ Already tagged 435ca987d46SWarner Losh else 436ca987d46SWarner Losh kerncapbuf 0 2swap strcat 437ca987d46SWarner Losh 2over strcat 438ca987d46SWarner Losh 5 pick 5 pick menu_caption[x][y] setenv 439ca987d46SWarner Losh then 440ca987d46SWarner Losh else 441ca987d46SWarner Losh drop ( getenv cruft ) 442ca987d46SWarner Losh then 443ca987d46SWarner Losh 444ca987d46SWarner Losh 2over ansi_caption[x][y] getenv dup -1 <> if 445ca987d46SWarner Losh 2dup + 1- c@ [char] ) = if 446ca987d46SWarner Losh 2drop \ Already tagged 447ca987d46SWarner Losh else 448ca987d46SWarner Losh kerncapbuf 0 2swap strcat 449ca987d46SWarner Losh 2over strcat 450ca987d46SWarner Losh 5 pick 5 pick ansi_caption[x][y] setenv 451ca987d46SWarner Losh then 452ca987d46SWarner Losh else 453ca987d46SWarner Losh drop ( getenv cruft ) 454ca987d46SWarner Losh then 455ca987d46SWarner Losh 456ca987d46SWarner Losh rot 1+ dup [char] 8 > if 457ca987d46SWarner Losh -rot 2drop TRUE ( break ) 458ca987d46SWarner Losh else 459ca987d46SWarner Losh -rot FALSE 460ca987d46SWarner Losh then 461ca987d46SWarner Losh until 462ca987d46SWarner Losh 2drop ( x y -- ) 463ca987d46SWarner Losh; 464ca987d46SWarner Losh 465ca987d46SWarner Losh\ This function creates the list of menu items. This function is called by the 466ca987d46SWarner Losh\ menu-display function. You need not call it directly. 467ca987d46SWarner Losh\ 468ca987d46SWarner Losh: menu-create ( -- ) 469ca987d46SWarner Losh 470ca987d46SWarner Losh \ Print the frame caption at (x,y) 471ca987d46SWarner Losh s" loader_menu_title" getenv dup -1 = if 472ca987d46SWarner Losh drop s" Welcome to FreeBSD" 473ca987d46SWarner Losh then 474ca987d46SWarner Losh TRUE ( use default alignment ) 475ca987d46SWarner Losh s" loader_menu_title_align" getenv dup -1 <> if 476ca987d46SWarner Losh 2dup s" left" compare-insensitive 0= if ( 1 ) 477ca987d46SWarner Losh 2drop ( c-addr/u ) drop ( bool ) 478ca987d46SWarner Losh menuX @ menuY @ 1- 479ca987d46SWarner Losh FALSE ( don't use default alignment ) 480ca987d46SWarner Losh else ( 1 ) 2dup s" right" compare-insensitive 0= if ( 2 ) 481ca987d46SWarner Losh 2drop ( c-addr/u ) drop ( bool ) 482ca987d46SWarner Losh menuX @ 42 + 4 - over - menuY @ 1- 483ca987d46SWarner Losh FALSE ( don't use default alignment ) 484ca987d46SWarner Losh else ( 2 ) 2drop ( c-addr/u ) then ( 1 ) then 485ca987d46SWarner Losh else 486ca987d46SWarner Losh drop ( getenv cruft ) 487ca987d46SWarner Losh then 488ca987d46SWarner Losh if ( use default center alignement? ) 489ca987d46SWarner Losh menuX @ 19 + over 2 / - menuY @ 1- 490ca987d46SWarner Losh then 49162ffcaabSToomas Soome swap 1- swap 4924ba91fa0SToomas Soome at-xy dup 0= if 4934ba91fa0SToomas Soome 2drop ( empty loader_menu_title ) 4944ba91fa0SToomas Soome else 4954ba91fa0SToomas Soome space type space 4964ba91fa0SToomas Soome then 497ca987d46SWarner Losh 498ca987d46SWarner Losh \ If $menu_init is set, evaluate it (allowing for whole menus to be 499ca987d46SWarner Losh \ constructed dynamically -- as this function could conceivably set 500ca987d46SWarner Losh \ the remaining environment variables to construct the menu entirely). 501ca987d46SWarner Losh \ 502ca987d46SWarner Losh s" menu_init" getenv dup -1 <> if 503ca987d46SWarner Losh evaluate 504ca987d46SWarner Losh else 505ca987d46SWarner Losh drop 506ca987d46SWarner Losh then 507ca987d46SWarner Losh 508ca987d46SWarner Losh \ Print our menu options with respective key/variable associations. 509ca987d46SWarner Losh \ `printmenuitem' ends by adding the decimal ASCII value for the 510ca987d46SWarner Losh \ numerical prefix to the stack. We store the value left on the stack 511ca987d46SWarner Losh \ to the key binding variable for later testing against a character 512ca987d46SWarner Losh \ captured by the `getkey' function. 513ca987d46SWarner Losh 514ca987d46SWarner Losh \ Note that any menu item beyond 9 will have a numerical prefix on the 515ca987d46SWarner Losh \ screen consisting of the first digit (ie. 1 for the tenth menu item) 516ca987d46SWarner Losh \ and the key required to activate that menu item will be the decimal 517ca987d46SWarner Losh \ ASCII of 48 plus the menu item (ie. 58 for the tenth item, aka. `:') 518ca987d46SWarner Losh \ which is misleading and not desirable. 519ca987d46SWarner Losh \ 520ca987d46SWarner Losh \ Thus, we do not allow more than 8 configurable items on the menu 521ca987d46SWarner Losh \ (with "Reboot" as the optional ninth and highest numbered item). 522ca987d46SWarner Losh 523ca987d46SWarner Losh \ 524ca987d46SWarner Losh \ Initialize the ACPI option status. 525ca987d46SWarner Losh \ 526ca987d46SWarner Losh 0 menuacpi ! 527ca987d46SWarner Losh s" menu_acpi" getenv -1 <> if 528ca987d46SWarner Losh c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' ) 529ca987d46SWarner Losh menuacpi ! 530ca987d46SWarner Losh arch-i386? if acpipresent? if 531ca987d46SWarner Losh \ 532ca987d46SWarner Losh \ Set menu toggle state to active state 533ca987d46SWarner Losh \ (required by generic toggle_menuitem) 534ca987d46SWarner Losh \ 535ca987d46SWarner Losh acpienabled? menuacpi @ toggle_stateN ! 536ca987d46SWarner Losh then then 537ca987d46SWarner Losh else 538ca987d46SWarner Losh drop 539ca987d46SWarner Losh then 540ca987d46SWarner Losh then 541ca987d46SWarner Losh 542ca987d46SWarner Losh \ 543ca987d46SWarner Losh \ Initialize kernel captions after parsing $kernels 544ca987d46SWarner Losh \ 545ca987d46SWarner Losh 0 menukernel ! 546ca987d46SWarner Losh s" menu_kernel" getenv -1 <> if 547ca987d46SWarner Losh c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' ) 548ca987d46SWarner Losh dup menukernel ! 549ca987d46SWarner Losh dup parse-kernels tag-kernels 550ca987d46SWarner Losh 551ca987d46SWarner Losh \ Get the current cycle state (entry to use) 552ca987d46SWarner Losh s" kernel_state" evaluate @ 48 + ( n -- n y ) 553ca987d46SWarner Losh 554ca987d46SWarner Losh \ If state is invalid, reset 555ca987d46SWarner Losh dup kernmenuidx @ 1- > if 556ca987d46SWarner Losh drop [char] 0 ( n y -- n 48 ) 557ca987d46SWarner Losh 0 s" kernel_state" evaluate ! 558ca987d46SWarner Losh over s" init_kernel" evaluate drop 559ca987d46SWarner Losh then 560ca987d46SWarner Losh 561ca987d46SWarner Losh \ Set the current non-ANSI caption 562ca987d46SWarner Losh 2dup swap dup ( n y -- n y y n n ) 563ca987d46SWarner Losh s" set menu_caption[x]=$menu_caption[x][y]" 564ca987d46SWarner Losh 17 +c! 34 +c! 37 +c! evaluate 565ca987d46SWarner Losh ( n y y n n c-addr/u -- n y ) 566ca987d46SWarner Losh 567ca987d46SWarner Losh \ Set the current ANSI caption 568ca987d46SWarner Losh 2dup swap dup ( n y -- n y y n n ) 569ca987d46SWarner Losh s" set ansi_caption[x]=$ansi_caption[x][y]" 570ca987d46SWarner Losh 17 +c! 34 +c! 37 +c! evaluate 571ca987d46SWarner Losh ( n y y n n c-addr/u -- n y ) 572ca987d46SWarner Losh 573ca987d46SWarner Losh \ Initialize cycle state from stored value 574ca987d46SWarner Losh 48 - ( n y -- n k ) 575ca987d46SWarner Losh s" init_cyclestate" evaluate ( n k -- n ) 576ca987d46SWarner Losh 577ca987d46SWarner Losh \ Set $kernel to $kernel[y] 578ca987d46SWarner Losh s" activate_kernel" evaluate ( n -- n ) 579ca987d46SWarner Losh then 580ca987d46SWarner Losh drop 581ca987d46SWarner Losh then 582ca987d46SWarner Losh 583ca987d46SWarner Losh \ 584ca987d46SWarner Losh \ Initialize the menu_options visual separator. 585ca987d46SWarner Losh \ 586ca987d46SWarner Losh 0 menuoptions ! 587ca987d46SWarner Losh s" menu_options" getenv -1 <> if 588ca987d46SWarner Losh c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' ) 589ca987d46SWarner Losh menuoptions ! 590ca987d46SWarner Losh else 591ca987d46SWarner Losh drop 592ca987d46SWarner Losh then 593ca987d46SWarner Losh then 594ca987d46SWarner Losh 595ca987d46SWarner Losh \ Initialize "Reboot" menu state variable (prevents double-entry) 596ca987d46SWarner Losh false menurebootadded ! 597ca987d46SWarner Losh 598ca987d46SWarner Losh menu_start 599ca987d46SWarner Losh 1- menuidx ! \ Initialize the starting index for the menu 600ca987d46SWarner Losh 0 menurow ! \ Initialize the starting position for the menu 601ca987d46SWarner Losh 602ca987d46SWarner Losh 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8') 603ca987d46SWarner Losh begin 604ca987d46SWarner Losh \ If the "Options:" separator, print it. 605ca987d46SWarner Losh dup menuoptions @ = if 606ca987d46SWarner Losh \ Optionally add a reboot option to the menu 607ca987d46SWarner Losh s" menu_reboot" getenv -1 <> if 608ca987d46SWarner Losh drop 609ca987d46SWarner Losh s" Reboot" printmenuitem menureboot ! 610ca987d46SWarner Losh true menurebootadded ! 611ca987d46SWarner Losh then 612ca987d46SWarner Losh 613ca987d46SWarner Losh menuX @ 614ca987d46SWarner Losh menurow @ 2 + menurow ! 615ca987d46SWarner Losh menurow @ menuY @ + 616ca987d46SWarner Losh at-xy 617ca987d46SWarner Losh s" menu_optionstext" getenv dup -1 <> if 618ca987d46SWarner Losh type 619ca987d46SWarner Losh else 620ca987d46SWarner Losh drop ." Options:" 621ca987d46SWarner Losh then 622ca987d46SWarner Losh then 623ca987d46SWarner Losh 624ca987d46SWarner Losh \ If this is the ACPI menu option, act accordingly. 625ca987d46SWarner Losh dup menuacpi @ = if 626ca987d46SWarner Losh dup acpimenuitem ( n -- n n c-addr/u | n n -1 ) 627ca987d46SWarner Losh dup -1 <> if 628ca987d46SWarner Losh 13 +c! ( n n c-addr/u -- n c-addr/u ) 629ca987d46SWarner Losh \ replace 'x' with n 630ca987d46SWarner Losh else 631ca987d46SWarner Losh swap drop ( n n -1 -- n -1 ) 632ca987d46SWarner Losh over menu_command[x] unsetenv 633ca987d46SWarner Losh then 634ca987d46SWarner Losh else 635ca987d46SWarner Losh \ make sure we have not already initialized this item 636ca987d46SWarner Losh dup init_stateN dup @ 0= if 637ca987d46SWarner Losh 1 swap ! 638ca987d46SWarner Losh 639ca987d46SWarner Losh \ If this menuitem has an initializer, run it 640ca987d46SWarner Losh dup menu_init[x] 641ca987d46SWarner Losh getenv dup -1 <> if 642ca987d46SWarner Losh evaluate 643ca987d46SWarner Losh else 644ca987d46SWarner Losh drop 645ca987d46SWarner Losh then 646ca987d46SWarner Losh else 647ca987d46SWarner Losh drop 648ca987d46SWarner Losh then 649ca987d46SWarner Losh 650ca987d46SWarner Losh dup 651ca987d46SWarner Losh loader_color? if 652ca987d46SWarner Losh ansi_caption[x] 653ca987d46SWarner Losh else 654ca987d46SWarner Losh menu_caption[x] 655ca987d46SWarner Losh then 656ca987d46SWarner Losh then 657ca987d46SWarner Losh 658ca987d46SWarner Losh dup -1 <> if 659ca987d46SWarner Losh \ test for environment variable 660ca987d46SWarner Losh getenv dup -1 <> if 661ca987d46SWarner Losh printmenuitem ( c-addr/u -- n ) 662ca987d46SWarner Losh dup menukeyN ! 663ca987d46SWarner Losh else 664ca987d46SWarner Losh drop 665ca987d46SWarner Losh then 666ca987d46SWarner Losh else 667ca987d46SWarner Losh drop 668ca987d46SWarner Losh then 669ca987d46SWarner Losh 670ca987d46SWarner Losh 1+ dup 56 > \ add 1 to iterator, continue if less than 57 671ca987d46SWarner Losh until 672ca987d46SWarner Losh drop \ iterator 673ca987d46SWarner Losh 674ca987d46SWarner Losh \ Optionally add a reboot option to the menu 675ca987d46SWarner Losh menurebootadded @ true <> if 676ca987d46SWarner Losh s" menu_reboot" getenv -1 <> if 677ca987d46SWarner Losh drop \ no need for the value 678ca987d46SWarner Losh s" Reboot" \ menu caption (required by printmenuitem) 679ca987d46SWarner Losh 680ca987d46SWarner Losh printmenuitem 681ca987d46SWarner Losh menureboot ! 682ca987d46SWarner Losh else 683ca987d46SWarner Losh 0 menureboot ! 684ca987d46SWarner Losh then 685ca987d46SWarner Losh then 686ca987d46SWarner Losh; 687ca987d46SWarner Losh 688ca987d46SWarner Losh\ Takes a single integer on the stack and updates the timeout display. The 689ca987d46SWarner Losh\ integer must be between 0 and 9 (we will only update a single digit in the 690ca987d46SWarner Losh\ source message). 691ca987d46SWarner Losh\ 692ca987d46SWarner Losh: menu-timeout-update ( N -- ) 693ca987d46SWarner Losh 694ca987d46SWarner Losh \ Enforce minimum/maximum 695ca987d46SWarner Losh dup 9 > if drop 9 then 696ca987d46SWarner Losh dup 0 < if drop 0 then 697ca987d46SWarner Losh 698ca987d46SWarner Losh s" Autoboot in N seconds. [Space] to pause" ( n -- n c-addr/u ) 699ca987d46SWarner Losh 700ca987d46SWarner Losh 2 pick 0> if 701ca987d46SWarner Losh rot 48 + -rot ( n c-addr/u -- n' c-addr/u ) \ convert to ASCII 702ca987d46SWarner Losh 12 +c! ( n' c-addr/u -- c-addr/u ) \ replace 'N' above 703ca987d46SWarner Losh 704ca987d46SWarner Losh menu_timeout_x @ menu_timeout_y @ at-xy \ position cursor 705ca987d46SWarner Losh type ( c-addr/u -- ) \ print message 706ca987d46SWarner Losh else 707ca987d46SWarner Losh menu_timeout_x @ menu_timeout_y @ at-xy \ position cursor 708ca987d46SWarner Losh spaces ( n c-addr/u -- n c-addr ) \ erase message 709ca987d46SWarner Losh 2drop ( n c-addr -- ) 710ca987d46SWarner Losh then 711ca987d46SWarner Losh 712ca987d46SWarner Losh 0 25 at-xy ( position cursor back at bottom-left ) 713ca987d46SWarner Losh; 714ca987d46SWarner Losh 715ca987d46SWarner Losh\ This function blocks program flow (loops forever) until a key is pressed. 716ca987d46SWarner Losh\ The key that was pressed is added to the top of the stack in the form of its 717ca987d46SWarner Losh\ decimal ASCII representation. This function is called by the menu-display 718ca987d46SWarner Losh\ function. You need not call it directly. 719ca987d46SWarner Losh\ 720ca987d46SWarner Losh: getkey ( -- ascii_keycode ) 721ca987d46SWarner Losh 722ca987d46SWarner Losh begin \ loop forever 723ca987d46SWarner Losh 724ca987d46SWarner Losh menu_timeout_enabled @ 1 = if 725ca987d46SWarner Losh ( -- ) 726ca987d46SWarner Losh seconds ( get current time: -- N ) 727ca987d46SWarner Losh dup menu_time @ <> if ( has time elapsed?: N N N -- N ) 728ca987d46SWarner Losh 729ca987d46SWarner Losh \ At least 1 second has elapsed since last loop 730ca987d46SWarner Losh \ so we will decrement our "timeout" (really a 731ca987d46SWarner Losh \ counter, insuring that we do not proceed too 732ca987d46SWarner Losh \ fast) and update our timeout display. 733ca987d46SWarner Losh 734ca987d46SWarner Losh menu_time ! ( update time record: N -- ) 735ca987d46SWarner Losh menu_timeout @ ( "time" remaining: -- N ) 736ca987d46SWarner Losh dup 0> if ( greater than 0?: N N 0 -- N ) 737ca987d46SWarner Losh 1- ( decrement counter: N -- N ) 738ca987d46SWarner Losh dup menu_timeout ! 739ca987d46SWarner Losh ( re-assign: N N Addr -- N ) 740ca987d46SWarner Losh then 741ca987d46SWarner Losh ( -- N ) 742ca987d46SWarner Losh 743ca987d46SWarner Losh dup 0= swap 0< or if ( N <= 0?: N N -- ) 744ca987d46SWarner Losh \ halt the timer 745ca987d46SWarner Losh 0 menu_timeout ! ( 0 Addr -- ) 746ca987d46SWarner Losh 0 menu_timeout_enabled ! ( 0 Addr -- ) 747ca987d46SWarner Losh then 748ca987d46SWarner Losh 749ca987d46SWarner Losh \ update the timer display ( N -- ) 750ca987d46SWarner Losh menu_timeout @ menu-timeout-update 751ca987d46SWarner Losh 752ca987d46SWarner Losh menu_timeout @ 0= if 753ca987d46SWarner Losh \ We've reached the end of the timeout 754ca987d46SWarner Losh \ (user did not cancel by pressing ANY 755ca987d46SWarner Losh \ key) 756ca987d46SWarner Losh 757ca987d46SWarner Losh s" menu_timeout_command" getenv dup 758ca987d46SWarner Losh -1 = if 759ca987d46SWarner Losh drop \ clean-up 760ca987d46SWarner Losh else 761ca987d46SWarner Losh evaluate 762ca987d46SWarner Losh then 763ca987d46SWarner Losh then 764ca987d46SWarner Losh 765ca987d46SWarner Losh else ( -- N ) 766ca987d46SWarner Losh \ No [detectable] time has elapsed (in seconds) 767ca987d46SWarner Losh drop ( N -- ) 768ca987d46SWarner Losh then 769ca987d46SWarner Losh ( -- ) 770ca987d46SWarner Losh then 771ca987d46SWarner Losh 772ca987d46SWarner Losh key? if \ Was a key pressed? (see loader(8)) 773ca987d46SWarner Losh 774ca987d46SWarner Losh \ An actual key was pressed (if the timeout is running, 775ca987d46SWarner Losh \ kill it regardless of which key was pressed) 776ca987d46SWarner Losh menu_timeout @ 0<> if 777ca987d46SWarner Losh 0 menu_timeout ! 778ca987d46SWarner Losh 0 menu_timeout_enabled ! 779ca987d46SWarner Losh 780ca987d46SWarner Losh \ clear screen of timeout message 781ca987d46SWarner Losh 0 menu-timeout-update 782ca987d46SWarner Losh then 783ca987d46SWarner Losh 784ca987d46SWarner Losh \ get the key that was pressed and exit (if we 785ca987d46SWarner Losh \ get a non-zero ASCII code) 786ca987d46SWarner Losh key dup 0<> if 787ca987d46SWarner Losh exit 788ca987d46SWarner Losh else 789ca987d46SWarner Losh drop 790ca987d46SWarner Losh then 791ca987d46SWarner Losh then 792ca987d46SWarner Losh 50 ms \ sleep for 50 milliseconds (see loader(8)) 793ca987d46SWarner Losh 794ca987d46SWarner Losh again 795ca987d46SWarner Losh; 796ca987d46SWarner Losh 797ca987d46SWarner Losh: menu-erase ( -- ) \ Erases menu and resets positioning variable to position 1. 798ca987d46SWarner Losh 799ca987d46SWarner Losh \ Clear the screen area associated with the interactive menu 800ca987d46SWarner Losh menuX @ menuY @ 801ca987d46SWarner Losh 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+ 802ca987d46SWarner Losh 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+ 803ca987d46SWarner Losh 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+ 804ca987d46SWarner Losh 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+ 805ca987d46SWarner Losh 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+ 806ca987d46SWarner Losh 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 807ca987d46SWarner Losh 2drop 808ca987d46SWarner Losh 809ca987d46SWarner Losh \ Reset the starting index and position for the menu 810ca987d46SWarner Losh menu_start 1- menuidx ! 811ca987d46SWarner Losh 0 menurow ! 812ca987d46SWarner Losh; 813ca987d46SWarner Losh 814ca987d46SWarner Loshonly forth 815ca987d46SWarner Loshalso menu-infrastructure 816ca987d46SWarner Loshalso menu-namespace 817ca987d46SWarner Loshalso menu-command-helpers definitions 818ca987d46SWarner Losh 819ca987d46SWarner Losh: toggle_menuitem ( N -- N ) \ toggles caption text and internal menuitem state 820ca987d46SWarner Losh 821ca987d46SWarner Losh \ ASCII numeral equal to user-selected menu item must be on the stack. 822ca987d46SWarner Losh \ We do not modify the stack, so the ASCII numeral is left on top. 823ca987d46SWarner Losh 824ca987d46SWarner Losh dup init_textN c@ 0= if 825ca987d46SWarner Losh \ NOTE: no need to check toggle_stateN since the first time we 826ca987d46SWarner Losh \ are called, we will populate init_textN. Further, we don't 827ca987d46SWarner Losh \ need to test whether menu_caption[x] (ansi_caption[x] when 828ca987d46SWarner Losh \ loader_color?=1) is available since we would not have been 829ca987d46SWarner Losh \ called if the caption was NULL. 830ca987d46SWarner Losh 831ca987d46SWarner Losh \ base name of environment variable 832ca987d46SWarner Losh dup ( n -- n n ) \ key pressed 833ca987d46SWarner Losh loader_color? if 834ca987d46SWarner Losh ansi_caption[x] 835ca987d46SWarner Losh else 836ca987d46SWarner Losh menu_caption[x] 837ca987d46SWarner Losh then 838ca987d46SWarner Losh getenv dup -1 <> if 839ca987d46SWarner Losh 840ca987d46SWarner Losh 2 pick ( n c-addr/u -- n c-addr/u n ) 841ca987d46SWarner Losh init_textN ( n c-addr/u n -- n c-addr/u c-addr ) 842ca987d46SWarner Losh 843ca987d46SWarner Losh \ now we have the buffer c-addr on top 844ca987d46SWarner Losh \ ( followed by c-addr/u of current caption ) 845ca987d46SWarner Losh 846ca987d46SWarner Losh \ Copy the current caption into our buffer 847ca987d46SWarner Losh 2dup c! -rot \ store strlen at first byte 848ca987d46SWarner Losh begin 849ca987d46SWarner Losh rot 1+ \ bring alt addr to top and increment 850ca987d46SWarner Losh -rot -rot \ bring buffer addr to top 851ca987d46SWarner Losh 2dup c@ swap c! \ copy current character 852ca987d46SWarner Losh 1+ \ increment buffer addr 853ca987d46SWarner Losh rot 1- \ bring buffer len to top and decrement 854ca987d46SWarner Losh dup 0= \ exit loop if buffer len is zero 855ca987d46SWarner Losh until 856ca987d46SWarner Losh 2drop \ buffer len/addr 857ca987d46SWarner Losh drop \ alt addr 858ca987d46SWarner Losh 859ca987d46SWarner Losh else 860ca987d46SWarner Losh drop 861ca987d46SWarner Losh then 862ca987d46SWarner Losh then 863ca987d46SWarner Losh 864ca987d46SWarner Losh \ Now we are certain to have init_textN populated with the initial 865ca987d46SWarner Losh \ value of menu_caption[x] (ansi_caption[x] with loader_color enabled). 866ca987d46SWarner Losh \ We can now use init_textN as the untoggled caption and 867ca987d46SWarner Losh \ toggled_text[x] (toggled_ansi[x] with loader_color enabled) as the 868ca987d46SWarner Losh \ toggled caption and store the appropriate value into menu_caption[x] 869ca987d46SWarner Losh \ (again, ansi_caption[x] with loader_color enabled). Last, we'll 870ca987d46SWarner Losh \ negate the toggled state so that we reverse the flow on subsequent 871ca987d46SWarner Losh \ calls. 872ca987d46SWarner Losh 873ca987d46SWarner Losh dup toggle_stateN @ 0= if 874ca987d46SWarner Losh \ state is OFF, toggle to ON 875ca987d46SWarner Losh 876ca987d46SWarner Losh dup ( n -- n n ) \ key pressed 877ca987d46SWarner Losh loader_color? if 878ca987d46SWarner Losh toggled_ansi[x] 879ca987d46SWarner Losh else 880ca987d46SWarner Losh toggled_text[x] 881ca987d46SWarner Losh then 882ca987d46SWarner Losh getenv dup -1 <> if 883ca987d46SWarner Losh \ Assign toggled text to menu caption 884ca987d46SWarner Losh 2 pick ( n c-addr/u -- n c-addr/u n ) \ key pressed 885ca987d46SWarner Losh loader_color? if 886ca987d46SWarner Losh ansi_caption[x] 887ca987d46SWarner Losh else 888ca987d46SWarner Losh menu_caption[x] 889ca987d46SWarner Losh then 890ca987d46SWarner Losh setenv 891ca987d46SWarner Losh else 892ca987d46SWarner Losh \ No toggled text, keep the same caption 893ca987d46SWarner Losh drop ( n -1 -- n ) \ getenv cruft 894ca987d46SWarner Losh then 895ca987d46SWarner Losh 896ca987d46SWarner Losh true \ new value of toggle state var (to be stored later) 897ca987d46SWarner Losh else 898ca987d46SWarner Losh \ state is ON, toggle to OFF 899ca987d46SWarner Losh 900ca987d46SWarner Losh dup init_textN count ( n -- n c-addr/u ) 901ca987d46SWarner Losh 902ca987d46SWarner Losh \ Assign init_textN text to menu caption 903ca987d46SWarner Losh 2 pick ( n c-addr/u -- n c-addr/u n ) \ key pressed 904ca987d46SWarner Losh loader_color? if 905ca987d46SWarner Losh ansi_caption[x] 906ca987d46SWarner Losh else 907ca987d46SWarner Losh menu_caption[x] 908ca987d46SWarner Losh then 909ca987d46SWarner Losh setenv 910ca987d46SWarner Losh 911ca987d46SWarner Losh false \ new value of toggle state var (to be stored below) 912ca987d46SWarner Losh then 913ca987d46SWarner Losh 914ca987d46SWarner Losh \ now we'll store the new toggle state (on top of stack) 915ca987d46SWarner Losh over toggle_stateN ! 916ca987d46SWarner Losh; 917ca987d46SWarner Losh 918ca987d46SWarner Losh: cycle_menuitem ( N -- N ) \ cycles through array of choices for a menuitem 919ca987d46SWarner Losh 920ca987d46SWarner Losh \ ASCII numeral equal to user-selected menu item must be on the stack. 921ca987d46SWarner Losh \ We do not modify the stack, so the ASCII numeral is left on top. 922ca987d46SWarner Losh 923ca987d46SWarner Losh dup cycle_stateN dup @ 1+ \ get value and increment 924ca987d46SWarner Losh 925ca987d46SWarner Losh \ Before assigning the (incremented) value back to the pointer, 926ca987d46SWarner Losh \ let's test for the existence of this particular array element. 927ca987d46SWarner Losh \ If the element exists, we'll store index value and move on. 928ca987d46SWarner Losh \ Otherwise, we'll loop around to zero and store that. 929ca987d46SWarner Losh 930ca987d46SWarner Losh dup 48 + ( n addr k -- n addr k k' ) 931ca987d46SWarner Losh \ duplicate array index and convert to ASCII numeral 932ca987d46SWarner Losh 933ca987d46SWarner Losh 3 pick swap ( n addr k k' -- n addr k n k' ) \ (n,k') as (x,y) 934ca987d46SWarner Losh loader_color? if 935ca987d46SWarner Losh ansi_caption[x][y] 936ca987d46SWarner Losh else 937ca987d46SWarner Losh menu_caption[x][y] 938ca987d46SWarner Losh then 939ca987d46SWarner Losh ( n addr k n k' -- n addr k c-addr/u ) 940ca987d46SWarner Losh 941ca987d46SWarner Losh \ Now test for the existence of our incremented array index in the 942ca987d46SWarner Losh \ form of $menu_caption[x][y] ($ansi_caption[x][y] with loader_color 943ca987d46SWarner Losh \ enabled) as set in loader.rc(5), et. al. 944ca987d46SWarner Losh 945ca987d46SWarner Losh getenv dup -1 = if 946ca987d46SWarner Losh \ No caption set for this array index. Loop back to zero. 947ca987d46SWarner Losh 948ca987d46SWarner Losh drop ( n addr k -1 -- n addr k ) \ getenv cruft 949ca987d46SWarner Losh drop 0 ( n addr k -- n addr 0 ) \ new value to store later 950ca987d46SWarner Losh 951ca987d46SWarner Losh 2 pick [char] 0 ( n addr 0 -- n addr 0 n 48 ) \ (n,48) as (x,y) 952ca987d46SWarner Losh loader_color? if 953ca987d46SWarner Losh ansi_caption[x][y] 954ca987d46SWarner Losh else 955ca987d46SWarner Losh menu_caption[x][y] 956ca987d46SWarner Losh then 957ca987d46SWarner Losh ( n addr 0 n 48 -- n addr 0 c-addr/u ) 958ca987d46SWarner Losh getenv dup -1 = if 959ca987d46SWarner Losh \ Highly unlikely to occur, but to ensure things move 960ca987d46SWarner Losh \ along smoothly, allocate a temporary NULL string 961ca987d46SWarner Losh drop ( cruft ) s" " 962ca987d46SWarner Losh then 963ca987d46SWarner Losh then 964ca987d46SWarner Losh 965ca987d46SWarner Losh \ At this point, we should have the following on the stack (in order, 966ca987d46SWarner Losh \ from bottom to top): 967ca987d46SWarner Losh \ 968ca987d46SWarner Losh \ n - Ascii numeral representing the menu choice (inherited) 969ca987d46SWarner Losh \ addr - address of our internal cycle_stateN variable 970ca987d46SWarner Losh \ k - zero-based number we intend to store to the above 971ca987d46SWarner Losh \ c-addr/u - string value we intend to store to menu_caption[x] 972ca987d46SWarner Losh \ (or ansi_caption[x] with loader_color enabled) 973ca987d46SWarner Losh \ 974ca987d46SWarner Losh \ Let's perform what we need to with the above. 975ca987d46SWarner Losh 976ca987d46SWarner Losh \ Assign array value text to menu caption 977ca987d46SWarner Losh 4 pick ( n addr k c-addr/u -- n addr k c-addr/u n ) 978ca987d46SWarner Losh loader_color? if 979ca987d46SWarner Losh ansi_caption[x] 980ca987d46SWarner Losh else 981ca987d46SWarner Losh menu_caption[x] 982ca987d46SWarner Losh then 983ca987d46SWarner Losh setenv 984ca987d46SWarner Losh 985ca987d46SWarner Losh swap ! ( n addr k -- n ) \ update array state variable 986ca987d46SWarner Losh; 987ca987d46SWarner Losh 988ca987d46SWarner Loshonly forth definitions also menu-infrastructure 989ca987d46SWarner Losh 990ca987d46SWarner Losh\ Erase and redraw the menu. Useful if you change a caption and want to 991ca987d46SWarner Losh\ update the menu to reflect the new value. 992ca987d46SWarner Losh\ 993ca987d46SWarner Losh: menu-redraw ( -- ) 994ca987d46SWarner Losh menu-erase 995ca987d46SWarner Losh menu-create 996ca987d46SWarner Losh; 997ca987d46SWarner Losh 9983630506bSToomas Soome: menu-box 9993630506bSToomas Soome f_double ( default frame type ) 10003630506bSToomas Soome \ Interpret a custom frame type for the menu 10013630506bSToomas Soome TRUE ( draw a box? default yes, but might be altered below ) 10023630506bSToomas Soome s" loader_menu_frame" getenv dup -1 = if ( 1 ) 10033630506bSToomas Soome drop \ no custom frame type 10043630506bSToomas Soome else ( 1 ) 2dup s" single" compare-insensitive 0= if ( 2 ) 10053630506bSToomas Soome f_single ( see frames.4th ) 10063630506bSToomas Soome else ( 2 ) 2dup s" double" compare-insensitive 0= if ( 3 ) 10073630506bSToomas Soome f_double ( see frames.4th ) 10083630506bSToomas Soome else ( 3 ) s" none" compare-insensitive 0= if ( 4 ) 10093630506bSToomas Soome drop FALSE \ don't draw a box 10103630506bSToomas Soome ( 4 ) then ( 3 ) then ( 2 ) then ( 1 ) then 10113630506bSToomas Soome if 10123630506bSToomas Soome 42 13 menuX @ 3 - menuY @ 1- box \ Draw frame (w,h,x,y) 10133630506bSToomas Soome then 10143630506bSToomas Soome; 10153630506bSToomas Soome 1016ca987d46SWarner Losh\ This function initializes the menu. Call this from your `loader.rc' file 1017ca987d46SWarner Losh\ before calling any other menu-related functions. 1018ca987d46SWarner Losh\ 1019ca987d46SWarner Losh: menu-init ( -- ) 1020ca987d46SWarner Losh menu_start 1021ca987d46SWarner Losh 1- menuidx ! \ Initialize the starting index for the menu 1022ca987d46SWarner Losh 0 menurow ! \ Initialize the starting position for the menu 1023ca987d46SWarner Losh 1024ca987d46SWarner Losh \ Assign configuration values 1025ca987d46SWarner Losh s" loader_menu_y" getenv dup -1 = if 1026ca987d46SWarner Losh drop \ no custom row position 1027ca987d46SWarner Losh menu_default_y 1028ca987d46SWarner Losh else 1029ca987d46SWarner Losh \ make sure custom position is a number 1030ca987d46SWarner Losh ?number 0= if 1031ca987d46SWarner Losh menu_default_y \ or use default 1032ca987d46SWarner Losh then 1033ca987d46SWarner Losh then 1034ca987d46SWarner Losh menuY ! 1035ca987d46SWarner Losh s" loader_menu_x" getenv dup -1 = if 1036ca987d46SWarner Losh drop \ no custom column position 1037ca987d46SWarner Losh menu_default_x 1038ca987d46SWarner Losh else 1039ca987d46SWarner Losh \ make sure custom position is a number 1040ca987d46SWarner Losh ?number 0= if 1041ca987d46SWarner Losh menu_default_x \ or use default 1042ca987d46SWarner Losh then 1043ca987d46SWarner Losh then 1044ca987d46SWarner Losh menuX ! 1045ca987d46SWarner Losh 10463630506bSToomas Soome ['] menu-box console-iterate 1047ca987d46SWarner Losh 0 25 at-xy \ Move cursor to the bottom for output 1048ca987d46SWarner Losh; 1049ca987d46SWarner Losh 1050ca987d46SWarner Loshalso menu-namespace 1051ca987d46SWarner Losh 1052ca987d46SWarner Losh\ Main function. Call this from your `loader.rc' file. 1053ca987d46SWarner Losh\ 1054ca987d46SWarner Losh: menu-display ( -- ) 1055ca987d46SWarner Losh 1056ca987d46SWarner Losh 0 menu_timeout_enabled ! \ start with automatic timeout disabled 1057ca987d46SWarner Losh 1058ca987d46SWarner Losh \ check indication that automatic execution after delay is requested 1059ca987d46SWarner Losh s" menu_timeout_command" getenv -1 <> if ( Addr C -1 -- | Addr ) 1060ca987d46SWarner Losh drop ( just testing existence right now: Addr -- ) 1061ca987d46SWarner Losh 1062ca987d46SWarner Losh \ initialize state variables 1063ca987d46SWarner Losh seconds menu_time ! ( store the time we started ) 1064ca987d46SWarner Losh 1 menu_timeout_enabled ! ( enable automatic timeout ) 1065ca987d46SWarner Losh 1066ca987d46SWarner Losh \ read custom time-duration (if set) 1067ca987d46SWarner Losh s" autoboot_delay" getenv dup -1 = if 1068ca987d46SWarner Losh drop \ no custom duration (remove dup'd bunk -1) 1069ca987d46SWarner Losh menu_timeout_default \ use default setting 1070ca987d46SWarner Losh else 1071ca987d46SWarner Losh 2dup ?number 0= if ( if not a number ) 1072ca987d46SWarner Losh \ disable timeout if "NO", else use default 1073ca987d46SWarner Losh s" NO" compare-insensitive 0= if 1074ca987d46SWarner Losh 0 menu_timeout_enabled ! 1075ca987d46SWarner Losh 0 ( assigned to menu_timeout below ) 1076ca987d46SWarner Losh else 1077ca987d46SWarner Losh menu_timeout_default 1078ca987d46SWarner Losh then 1079ca987d46SWarner Losh else 1080ca987d46SWarner Losh -rot 2drop 1081ca987d46SWarner Losh 1082ca987d46SWarner Losh \ boot immediately if less than zero 1083ca987d46SWarner Losh dup 0< if 1084ca987d46SWarner Losh drop 1085ca987d46SWarner Losh menu-create 1086ca987d46SWarner Losh 0 25 at-xy 1087ca987d46SWarner Losh 0 boot 1088ca987d46SWarner Losh then 1089ca987d46SWarner Losh then 1090ca987d46SWarner Losh then 1091ca987d46SWarner Losh menu_timeout ! ( store value on stack from above ) 1092ca987d46SWarner Losh 1093ca987d46SWarner Losh menu_timeout_enabled @ 1 = if 1094ca987d46SWarner Losh \ read custom column position (if set) 1095ca987d46SWarner Losh s" loader_menu_timeout_x" getenv dup -1 = if 1096ca987d46SWarner Losh drop \ no custom column position 1097ca987d46SWarner Losh menu_timeout_default_x \ use default setting 1098ca987d46SWarner Losh else 1099ca987d46SWarner Losh \ make sure custom position is a number 1100ca987d46SWarner Losh ?number 0= if 1101ca987d46SWarner Losh menu_timeout_default_x \ or use default 1102ca987d46SWarner Losh then 1103ca987d46SWarner Losh then 1104ca987d46SWarner Losh menu_timeout_x ! ( store value on stack from above ) 1105ca987d46SWarner Losh 1106ca987d46SWarner Losh \ read custom row position (if set) 1107ca987d46SWarner Losh s" loader_menu_timeout_y" getenv dup -1 = if 1108ca987d46SWarner Losh drop \ no custom row position 1109ca987d46SWarner Losh menu_timeout_default_y \ use default setting 1110ca987d46SWarner Losh else 1111ca987d46SWarner Losh \ make sure custom position is a number 1112ca987d46SWarner Losh ?number 0= if 1113ca987d46SWarner Losh menu_timeout_default_y \ or use default 1114ca987d46SWarner Losh then 1115ca987d46SWarner Losh then 1116ca987d46SWarner Losh menu_timeout_y ! ( store value on stack from above ) 1117ca987d46SWarner Losh then 1118ca987d46SWarner Losh then 1119ca987d46SWarner Losh 1120ca987d46SWarner Losh menu-create 1121ca987d46SWarner Losh 1122ca987d46SWarner Losh begin \ Loop forever 1123ca987d46SWarner Losh 1124ca987d46SWarner Losh 0 25 at-xy \ Move cursor to the bottom for output 1125ca987d46SWarner Losh getkey \ Block here, waiting for a key to be pressed 1126ca987d46SWarner Losh 1127ca987d46SWarner Losh dup -1 = if 1128ca987d46SWarner Losh drop exit \ Caught abort (abnormal return) 1129ca987d46SWarner Losh then 1130ca987d46SWarner Losh 1131ca987d46SWarner Losh \ Boot if the user pressed Enter/Ctrl-M (13) or 1132ca987d46SWarner Losh \ Ctrl-Enter/Ctrl-J (10) 1133ca987d46SWarner Losh dup over 13 = swap 10 = or if 1134ca987d46SWarner Losh drop ( no longer needed ) 1135ca987d46SWarner Losh s" boot" evaluate 1136ca987d46SWarner Losh exit ( pedantic; never reached ) 1137ca987d46SWarner Losh then 1138ca987d46SWarner Losh 1139ca987d46SWarner Losh dup menureboot @ = if 0 reboot then 1140ca987d46SWarner Losh 1141ca987d46SWarner Losh \ Evaluate the decimal ASCII value against known menu item 1142ca987d46SWarner Losh \ key associations and act accordingly 1143ca987d46SWarner Losh 1144ca987d46SWarner Losh 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8') 1145ca987d46SWarner Losh begin 1146ca987d46SWarner Losh dup menukeyN @ 1147ca987d46SWarner Losh rot tuck = if 1148ca987d46SWarner Losh 1149ca987d46SWarner Losh \ Adjust for missing ACPI menuitem on non-i386 1150ca987d46SWarner Losh arch-i386? true <> menuacpi @ 0<> and if 1151ca987d46SWarner Losh menuacpi @ over 2dup < -rot = or 1152ca987d46SWarner Losh over 58 < and if 1153ca987d46SWarner Losh ( key >= menuacpi && key < 58: N -- N ) 1154ca987d46SWarner Losh 1+ 1155ca987d46SWarner Losh then 1156ca987d46SWarner Losh then 1157ca987d46SWarner Losh 1158ca987d46SWarner Losh \ Test for the environment variable 1159ca987d46SWarner Losh dup menu_command[x] 1160ca987d46SWarner Losh getenv dup -1 <> if 1161ca987d46SWarner Losh \ Execute the stored procedure 1162ca987d46SWarner Losh evaluate 1163ca987d46SWarner Losh 1164ca987d46SWarner Losh \ We expect there to be a non-zero 1165ca987d46SWarner Losh \ value left on the stack after 1166ca987d46SWarner Losh \ executing the stored procedure. 1167ca987d46SWarner Losh \ If so, continue to run, else exit. 1168ca987d46SWarner Losh 1169ca987d46SWarner Losh 0= if 1170ca987d46SWarner Losh drop \ key pressed 1171ca987d46SWarner Losh drop \ loop iterator 1172ca987d46SWarner Losh exit 1173ca987d46SWarner Losh else 1174ca987d46SWarner Losh swap \ need iterator on top 1175ca987d46SWarner Losh then 1176ca987d46SWarner Losh then 1177ca987d46SWarner Losh 1178ca987d46SWarner Losh \ Re-adjust for missing ACPI menuitem 1179ca987d46SWarner Losh arch-i386? true <> menuacpi @ 0<> and if 1180ca987d46SWarner Losh swap 1181ca987d46SWarner Losh menuacpi @ 1+ over 2dup < -rot = or 1182ca987d46SWarner Losh over 59 < and if 1183ca987d46SWarner Losh 1- 1184ca987d46SWarner Losh then 1185ca987d46SWarner Losh swap 1186ca987d46SWarner Losh then 1187ca987d46SWarner Losh else 1188ca987d46SWarner Losh swap \ need iterator on top 1189ca987d46SWarner Losh then 1190ca987d46SWarner Losh 1191ca987d46SWarner Losh \ 1192ca987d46SWarner Losh \ Check for menu keycode shortcut(s) 1193ca987d46SWarner Losh \ 1194ca987d46SWarner Losh dup menu_keycode[x] 1195ca987d46SWarner Losh getenv dup -1 = if 1196ca987d46SWarner Losh drop 1197ca987d46SWarner Losh else 1198ca987d46SWarner Losh ?number 0<> if 1199ca987d46SWarner Losh rot tuck = if 1200ca987d46SWarner Losh swap 1201ca987d46SWarner Losh dup menu_command[x] 1202ca987d46SWarner Losh getenv dup -1 <> if 1203ca987d46SWarner Losh evaluate 1204ca987d46SWarner Losh 0= if 1205ca987d46SWarner Losh 2drop 1206ca987d46SWarner Losh exit 1207ca987d46SWarner Losh then 1208ca987d46SWarner Losh else 1209ca987d46SWarner Losh drop 1210ca987d46SWarner Losh then 1211ca987d46SWarner Losh else 1212ca987d46SWarner Losh swap 1213ca987d46SWarner Losh then 1214ca987d46SWarner Losh then 1215ca987d46SWarner Losh then 1216ca987d46SWarner Losh 1217ca987d46SWarner Losh 1+ dup 56 > \ increment iterator 1218ca987d46SWarner Losh \ continue if less than 57 1219ca987d46SWarner Losh until 1220ca987d46SWarner Losh drop \ loop iterator 1221ca987d46SWarner Losh drop \ key pressed 1222ca987d46SWarner Losh 1223ca987d46SWarner Losh again \ Non-operational key was pressed; repeat 1224ca987d46SWarner Losh; 1225ca987d46SWarner Losh 1226ca987d46SWarner Losh\ This function unsets all the possible environment variables associated with 1227ca987d46SWarner Losh\ creating the interactive menu. 1228ca987d46SWarner Losh\ 1229ca987d46SWarner Losh: menu-unset ( -- ) 1230ca987d46SWarner Losh 1231ca987d46SWarner Losh 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8') 1232ca987d46SWarner Losh begin 1233ca987d46SWarner Losh dup menu_init[x] unsetenv \ menu initializer 1234ca987d46SWarner Losh dup menu_command[x] unsetenv \ menu command 1235ca987d46SWarner Losh dup menu_caption[x] unsetenv \ menu caption 1236ca987d46SWarner Losh dup ansi_caption[x] unsetenv \ ANSI caption 1237ca987d46SWarner Losh dup menu_keycode[x] unsetenv \ menu keycode 1238ca987d46SWarner Losh dup toggled_text[x] unsetenv \ toggle_menuitem caption 1239ca987d46SWarner Losh dup toggled_ansi[x] unsetenv \ toggle_menuitem ANSI caption 1240ca987d46SWarner Losh 1241ca987d46SWarner Losh 48 \ Iterator start (inner range 48 to 57; ASCII '0' to '9') 1242ca987d46SWarner Losh begin 1243ca987d46SWarner Losh \ cycle_menuitem caption and ANSI caption 1244ca987d46SWarner Losh 2dup menu_caption[x][y] unsetenv 1245ca987d46SWarner Losh 2dup ansi_caption[x][y] unsetenv 1246ca987d46SWarner Losh 1+ dup 57 > 1247ca987d46SWarner Losh until 1248ca987d46SWarner Losh drop \ inner iterator 1249ca987d46SWarner Losh 1250ca987d46SWarner Losh 0 over menukeyN ! \ used by menu-create, menu-display 1251ca987d46SWarner Losh 0 over init_stateN ! \ used by menu-create 1252ca987d46SWarner Losh 0 over toggle_stateN ! \ used by toggle_menuitem 1253ca987d46SWarner Losh 0 over init_textN c! \ used by toggle_menuitem 1254ca987d46SWarner Losh 0 over cycle_stateN ! \ used by cycle_menuitem 1255ca987d46SWarner Losh 1256ca987d46SWarner Losh 1+ dup 56 > \ increment, continue if less than 57 1257ca987d46SWarner Losh until 1258ca987d46SWarner Losh drop \ iterator 1259ca987d46SWarner Losh 1260ca987d46SWarner Losh s" menu_timeout_command" unsetenv \ menu timeout command 1261ca987d46SWarner Losh s" menu_reboot" unsetenv \ Reboot menu option flag 1262ca987d46SWarner Losh s" menu_acpi" unsetenv \ ACPI menu option flag 1263ca987d46SWarner Losh s" menu_kernel" unsetenv \ Kernel menu option flag 1264ca987d46SWarner Losh s" menu_options" unsetenv \ Options separator flag 1265ca987d46SWarner Losh s" menu_optionstext" unsetenv \ separator display text 1266ca987d46SWarner Losh s" menu_init" unsetenv \ menu initializer 1267ca987d46SWarner Losh 1268ca987d46SWarner Losh 0 menureboot ! 1269ca987d46SWarner Losh 0 menuacpi ! 1270ca987d46SWarner Losh 0 menuoptions ! 1271ca987d46SWarner Losh; 1272ca987d46SWarner Losh 1273ca987d46SWarner Loshonly forth definitions also menu-infrastructure 1274ca987d46SWarner Losh 1275ca987d46SWarner Losh\ This function both unsets menu variables and visually erases the menu area 1276ca987d46SWarner Losh\ in-preparation for another menu. 1277ca987d46SWarner Losh\ 1278ca987d46SWarner Losh: menu-clear ( -- ) 1279ca987d46SWarner Losh menu-unset 1280ca987d46SWarner Losh menu-erase 1281ca987d46SWarner Losh; 1282ca987d46SWarner Losh 1283ca987d46SWarner Loshbullet menubllt ! 1284ca987d46SWarner Losh 1285ca987d46SWarner Loshalso menu-namespace 1286ca987d46SWarner Losh 1287ca987d46SWarner Losh\ Initialize our menu initialization state variables 1288ca987d46SWarner Losh0 init_state1 ! 1289ca987d46SWarner Losh0 init_state2 ! 1290ca987d46SWarner Losh0 init_state3 ! 1291ca987d46SWarner Losh0 init_state4 ! 1292ca987d46SWarner Losh0 init_state5 ! 1293ca987d46SWarner Losh0 init_state6 ! 1294ca987d46SWarner Losh0 init_state7 ! 1295ca987d46SWarner Losh0 init_state8 ! 1296ca987d46SWarner Losh 1297ca987d46SWarner Losh\ Initialize our boolean state variables 1298ca987d46SWarner Losh0 toggle_state1 ! 1299ca987d46SWarner Losh0 toggle_state2 ! 1300ca987d46SWarner Losh0 toggle_state3 ! 1301ca987d46SWarner Losh0 toggle_state4 ! 1302ca987d46SWarner Losh0 toggle_state5 ! 1303ca987d46SWarner Losh0 toggle_state6 ! 1304ca987d46SWarner Losh0 toggle_state7 ! 1305ca987d46SWarner Losh0 toggle_state8 ! 1306ca987d46SWarner Losh 1307ca987d46SWarner Losh\ Initialize our array state variables 1308ca987d46SWarner Losh0 cycle_state1 ! 1309ca987d46SWarner Losh0 cycle_state2 ! 1310ca987d46SWarner Losh0 cycle_state3 ! 1311ca987d46SWarner Losh0 cycle_state4 ! 1312ca987d46SWarner Losh0 cycle_state5 ! 1313ca987d46SWarner Losh0 cycle_state6 ! 1314ca987d46SWarner Losh0 cycle_state7 ! 1315ca987d46SWarner Losh0 cycle_state8 ! 1316ca987d46SWarner Losh 1317ca987d46SWarner Losh\ Initialize string containers 1318ca987d46SWarner Losh0 init_text1 c! 1319ca987d46SWarner Losh0 init_text2 c! 1320ca987d46SWarner Losh0 init_text3 c! 1321ca987d46SWarner Losh0 init_text4 c! 1322ca987d46SWarner Losh0 init_text5 c! 1323ca987d46SWarner Losh0 init_text6 c! 1324ca987d46SWarner Losh0 init_text7 c! 1325ca987d46SWarner Losh0 init_text8 c! 1326ca987d46SWarner Losh 1327ca987d46SWarner Loshonly forth definitions 1328