xref: /freebsd/stand/forth/menu.4th (revision 37798b1d5dd12cd5e842b6f99135a2e4af8cf9e0)
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