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