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