1 \ Copyright (c) 2003 Scott Long <scottl@freebsd.org>
2 \ Copyright (c) 2003 Aleksander Fafula <alex@fafula.com>
3 \ Copyright (c) 2006-2013 Devin Teske <dteske@FreeBSD.org>
6 \ Redistribution and use in source and binary forms, with or without
7 \ modification, are permitted provided that the following conditions
9 \ 1. Redistributions of source code must retain the above copyright
10 \ notice, this list of conditions and the following disclaimer.
11 \ 2. Redistributions in binary form must reproduce the above copyright
12 \ notice, this list of conditions and the following disclaimer in the
13 \ documentation and/or other materials provided with the distribution.
15 \ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 \ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 \ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 \ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 \ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 \ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 \ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 \ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 \ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 \ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 include /boot/frames.4th
34 f_double \ Set frames to double (see frames.4th). Replace with
35 \ f_single if you want single frames.
36 46 constant dot \ ASCII definition of a period (in decimal)
38 5 constant menu_default_x \ default column position of timeout
39 10 constant menu_default_y \ default row position of timeout msg
40 4 constant menu_timeout_default_x \ default column position of timeout
41 23 constant menu_timeout_default_y \ default row position of timeout msg
42 10 constant menu_timeout_default \ default timeout (in seconds)
44 \ Customize the following values with care
46 1 constant menu_start \ Numerical prefix of first menu item
47 dot constant bullet \ Menu bullet (appears after numerical prefix)
48 5 constant menu_x \ Row position of the menu (from the top)
49 10 constant menu_y \ Column position of the menu (from left side)
52 variable menuidx \ Menu item stack for number prefixes
53 variable menurow \ Menu item stack for positioning
54 variable menubllt \ Menu item bullet
57 variable menuX \ Menu X offset (columns)
58 variable menuY \ Menu Y offset (rows)
60 \ Menu-item key association/detection
70 variable menurebootadded
74 \ Menu timer [count-down] variables
75 variable menu_timeout_enabled \ timeout state (internal use only)
76 variable menu_time \ variable for tracking the passage of time
77 variable menu_timeout \ determined configurable delay duration
78 variable menu_timeout_x \ column position of timeout message
79 variable menu_timeout_y \ row position of timeout message
81 \ Menu initialization status variables
91 \ Boolean option status variables
92 variable toggle_state1
93 variable toggle_state2
94 variable toggle_state3
95 variable toggle_state4
96 variable toggle_state5
97 variable toggle_state6
98 variable toggle_state7
99 variable toggle_state8
101 \ Array option status variables
102 variable cycle_state1
103 variable cycle_state2
104 variable cycle_state3
105 variable cycle_state4
106 variable cycle_state5
107 variable cycle_state6
108 variable cycle_state7
109 variable cycle_state8
111 \ Containers for storing the initial caption text
112 create init_text1 255 allot
113 create init_text2 255 allot
114 create init_text3 255 allot
115 create init_text4 255 allot
116 create init_text5 255 allot
117 create init_text6 255 allot
118 create init_text7 255 allot
119 create init_text8 255 allot
121 : +c! ( N C-ADDR/U K -- C-ADDR/U )
122 3 pick 3 pick ( n c-addr/u k -- n c-addr/u k n c-addr )
123 rot + c! ( n c-addr/u k n c-addr -- n c-addr/u )
124 rot drop ( n c-addr/u -- c-addr/u )
127 : menukeyN ( N -- ADDR ) s" menukeyN" 7 +c! evaluate ;
128 : init_stateN ( N -- ADDR ) s" init_stateN" 10 +c! evaluate ;
129 : toggle_stateN ( N -- ADDR ) s" toggle_stateN" 12 +c! evaluate ;
130 : cycle_stateN ( N -- ADDR ) s" cycle_stateN" 11 +c! evaluate ;
131 : init_textN ( N -- C-ADDR ) s" init_textN" 9 +c! evaluate ;
133 : str_loader_menu_frame ( -- C-ADDR/U ) s" loader_menu_frame" ;
134 : str_loader_menu_title ( -- C-ADDR/U ) s" loader_menu_title" ;
135 : str_loader_menu_title_align ( -- C-ADDR/U ) s" loader_menu_title_align" ;
136 : str_loader_menu_x ( -- C-ADDR/U ) s" loader_menu_x" ;
137 : str_loader_menu_y ( -- C-ADDR/U ) s" loader_menu_y" ;
138 : str_loader_menu_timeout_x ( -- C-ADDR/U ) s" loader_menu_timeout_x" ;
139 : str_loader_menu_timeout_y ( -- C-ADDR/U ) s" loader_menu_timeout_y" ;
140 : str_menu_init ( -- C-ADDR/U ) s" menu_init" ;
141 : str_menu_timeout_command ( -- C-ADDR/U ) s" menu_timeout_command" ;
142 : str_menu_reboot ( -- C-ADDR/U ) s" menu_reboot" ;
143 : str_menu_acpi ( -- C-ADDR/U ) s" menu_acpi" ;
144 : str_menu_options ( -- C-ADDR/U ) s" menu_options" ;
145 : str_menu_optionstext ( -- C-ADDR/U ) s" menu_optionstext" ;
147 : str_menu_init[x] ( -- C-ADDR/U ) s" menu_init[x]" ;
148 : str_menu_command[x] ( -- C-ADDR/U ) s" menu_command[x]" ;
149 : str_menu_caption[x] ( -- C-ADDR/U ) s" menu_caption[x]" ;
150 : str_ansi_caption[x] ( -- C-ADDR/U ) s" ansi_caption[x]" ;
151 : str_menu_keycode[x] ( -- C-ADDR/U ) s" menu_keycode[x]" ;
152 : str_toggled_text[x] ( -- C-ADDR/U ) s" toggled_text[x]" ;
153 : str_toggled_ansi[x] ( -- C-ADDR/U ) s" toggled_ansi[x]" ;
154 : str_menu_caption[x][y] ( -- C-ADDR/U ) s" menu_caption[x][y]" ;
155 : str_ansi_caption[x][y] ( -- C-ADDR/U ) s" ansi_caption[x][y]" ;
157 : menu_init[x] ( N -- C-ADDR/U ) str_menu_init[x] 10 +c! ;
158 : menu_command[x] ( N -- C-ADDR/U ) str_menu_command[x] 13 +c! ;
159 : menu_caption[x] ( N -- C-ADDR/U ) str_menu_caption[x] 13 +c! ;
160 : ansi_caption[x] ( N -- C-ADDR/U ) str_ansi_caption[x] 13 +c! ;
161 : menu_keycode[x] ( N -- C-ADDR/U ) str_menu_keycode[x] 13 +c! ;
162 : toggled_text[x] ( N -- C-ADDR/U ) str_toggled_text[x] 13 +c! ;
163 : toggled_ansi[x] ( N -- C-ADDR/U ) str_toggled_ansi[x] 13 +c! ;
164 : menu_caption[x][y] ( N M -- C-ADDR/U ) str_menu_caption[x][y] 16 +c! 13 +c! ;
165 : ansi_caption[x][y] ( N M -- C-ADDR/U ) str_ansi_caption[x][y] 16 +c! 13 +c! ;
167 : arch-i386? ( -- BOOL ) \ Returns TRUE (-1) on i386, FALSE (0) otherwise.
168 s" arch-i386" environment? dup if
173 \ This function prints a menu item at menuX (row) and menuY (column), returns
174 \ the incremental decimal ASCII value associated with the menu item, and
175 \ increments the cursor position to the next row for the creation of the next
176 \ menu item. This function is called by the menu-create function. You need not
179 : printmenuitem ( menu_item_str -- ascii_keycode )
181 menurow dup @ 1+ swap ! ( increment menurow )
182 menuidx dup @ 1+ swap ! ( increment menuidx )
184 \ Calculate the menuitem row position
187 \ Position the cursor at the menuitem position
188 dup menuX @ swap at-xy
190 \ Print the value of menuidx
196 ."
\e[37m" (
\e[39m )
199 \ Move the cursor forward 1 column
200 dup menuX @ 1+ swap at-xy
202 menubllt @ emit \ Print the menu bullet using the emit function
204 \ Move the cursor to the 3rd column from the current position
205 \ to allow for a space between the numerical prefix and the
207 menuX @ 3 + swap at-xy
209 \ Print the menu caption (we expect a string to be on the stack
210 \ prior to invoking this function)
213 \ Here we will add the ASCII decimal of the numerical prefix
214 \ to the stack (decimal ASCII for `1' is 49) as a "return value"
218 : toggle_menuitem ( N -- N ) \ toggles caption text and internal menuitem state
220 \ ASCII numeral equal to user-selected menu item must be on the stack.
221 \ We do not modify the stack, so the ASCII numeral is left on top.
223 dup init_textN c@ 0= if
224 \ NOTE: no need to check toggle_stateN since the first time we
225 \ are called, we will populate init_textN. Further, we don't
226 \ need to test whether menu_caption[x] (ansi_caption[x] when
227 \ loader_color?=1) is available since we would not have been
228 \ called if the caption was NULL.
230 \ base name of environment variable
231 dup ( n -- n n ) \ key pressed
239 2 pick ( n c-addr/u -- n c-addr/u n )
240 init_textN ( n c-addr/u n -- n c-addr/u c-addr )
242 \ now we have the buffer c-addr on top
243 \ ( followed by c-addr/u of current caption )
245 \ Copy the current caption into our buffer
246 2dup c! -rot \ store strlen at first byte
248 rot 1+ \ bring alt addr to top and increment
249 -rot -rot \ bring buffer addr to top
250 2dup c@ swap c! \ copy current character
251 1+ \ increment buffer addr
252 rot 1- \ bring buffer len to top and decrement
253 dup 0= \ exit loop if buffer len is zero
255 2drop \ buffer len/addr
263 \ Now we are certain to have init_textN populated with the initial
264 \ value of menu_caption[x] (ansi_caption[x] with loader_color enabled).
265 \ We can now use init_textN as the untoggled caption and
266 \ toggled_text[x] (toggled_ansi[x] with loader_color enabled) as the
267 \ toggled caption and store the appropriate value into menu_caption[x]
268 \ (again, ansi_caption[x] with loader_color enabled). Last, we'll
269 \ negate the toggled state so that we reverse the flow on subsequent
272 dup toggle_stateN @ 0= if
273 \ state is OFF, toggle to ON
275 dup ( n -- n n ) \ key pressed
282 \ Assign toggled text to menu caption
283 2 pick ( n c-addr/u -- n c-addr/u n ) \ key pressed
291 \ No toggled text, keep the same caption
292 drop ( n -1 -- n ) \ getenv cruft
295 true \ new value of toggle state var (to be stored later)
297 \ state is ON, toggle to OFF
299 dup init_textN count ( n -- n c-addr/u )
301 \ Assign init_textN text to menu caption
302 2 pick ( n c-addr/u -- n c-addr/u n ) \ key pressed
310 false \ new value of toggle state var (to be stored below)
313 \ now we'll store the new toggle state (on top of stack)
317 : cycle_menuitem ( N -- N ) \ cycles through array of choices for a menuitem
319 \ ASCII numeral equal to user-selected menu item must be on the stack.
320 \ We do not modify the stack, so the ASCII numeral is left on top.
322 dup cycle_stateN dup @ 1+ \ get value and increment
324 \ Before assigning the (incremented) value back to the pointer,
325 \ let's test for the existence of this particular array element.
326 \ If the element exists, we'll store index value and move on.
327 \ Otherwise, we'll loop around to zero and store that.
329 dup 48 + ( n addr k -- n addr k k' )
330 \ duplicate array index and convert to ASCII numeral
332 3 pick swap ( n addr k k' -- n addr k n k' ) \ (n,k') as (x,y)
338 ( n addr k n k' -- n addr k c-addr/u )
340 \ Now test for the existence of our incremented array index in the
341 \ form of $menu_caption[x][y] ($ansi_caption[x][y] with loader_color
342 \ enabled) as set in loader.rc(5), et. al.
345 \ No caption set for this array index. Loop back to zero.
347 drop ( n addr k -1 -- n addr k ) \ getenv cruft
348 drop 0 ( n addr k -- n addr 0 ) \ new value to store later
350 2 pick [char] 0 ( n addr 0 -- n addr 0 n 48 ) \ (n,48) as (x,y)
356 ( n addr 0 n 48 -- n addr 0 c-addr/u )
358 \ This is highly unlikely to occur, but to make
359 \ sure that things move along smoothly, allocate
360 \ a temporary NULL string
362 drop ( n addr 0 -1 -- n addr 0 ) \ getenv cruft
363 s" " ( n addr 0 -- n addr 0 c-addr/u )
367 \ At this point, we should have the following on the stack (in order,
368 \ from bottom to top):
370 \ n - Ascii numeral representing the menu choice (inherited)
371 \ addr - address of our internal cycle_stateN variable
372 \ k - zero-based number we intend to store to the above
373 \ c-addr/u - string value we intend to store to menu_caption[x]
374 \ (or ansi_caption[x] with loader_color enabled)
376 \ Let's perform what we need to with the above.
378 \ Assign array value text to menu caption
379 4 pick ( n addr k c-addr/u -- n addr k c-addr/u n )
387 swap ! ( n addr k -- n ) \ update array state variable
390 : acpipresent? ( -- flag ) \ Returns TRUE if ACPI is present, FALSE otherwise
391 s" hint.acpi.0.rsdp" getenv
399 : acpienabled? ( -- flag ) \ Returns TRUE if ACPI is enabled, FALSE otherwise
400 s" hint.acpi.0.disabled" getenv
411 \ This function prints the appropriate menuitem basename to the stack if an
412 \ ACPI option is to be presented to the user, otherwise returns -1. Used
413 \ internally by menu-create, you need not (nor should you) call this directly.
415 : acpimenuitem ( -- C-Addr/U | -1 )
433 menuidx dup @ 1+ swap ! ( increment menuidx )
441 \ This function creates the list of menu items. This function is called by the
442 \ menu-display function. You need not be call it directly.
446 \ Print the frame caption at (x,y)
447 str_loader_menu_title getenv dup -1 = if
448 drop s" Welcome to FreeBSD"
450 TRUE ( use default alignment )
451 str_loader_menu_title_align getenv dup -1 <> if
452 2dup s" left" compare-insensitive 0= if ( 1 )
453 2drop ( c-addr/u ) drop ( bool )
455 FALSE ( don't use default alignment )
456 else ( 1 ) 2dup s" right" compare-insensitive 0= if ( 2 )
457 2drop ( c-addr/u ) drop ( bool )
458 menuX @ 42 + 4 - over - menuY @ 1-
459 FALSE ( don't use default alignment )
460 else ( 2 ) 2drop ( c-addr/u ) then ( 1 ) then
462 drop ( getenv cruft )
464 if ( use default center alignement? )
465 menuX @ 19 + over 2 / - menuY @ 1-
469 \ If $menu_init is set, evaluate it (allowing for whole menus to be
470 \ constructed dynamically -- as this function could conceivably set
471 \ the remaining environment variables to construct the menu entirely).
473 str_menu_init getenv dup -1 <> if
479 \ Print our menu options with respective key/variable associations.
480 \ `printmenuitem' ends by adding the decimal ASCII value for the
481 \ numerical prefix to the stack. We store the value left on the stack
482 \ to the key binding variable for later testing against a character
483 \ captured by the `getkey' function.
485 \ Note that any menu item beyond 9 will have a numerical prefix on the
486 \ screen consisting of the first digit (ie. 1 for the tenth menu item)
487 \ and the key required to activate that menu item will be the decimal
488 \ ASCII of 48 plus the menu item (ie. 58 for the tenth item, aka. `:')
489 \ which is misleading and not desirable.
491 \ Thus, we do not allow more than 8 configurable items on the menu
492 \ (with "Reboot" as the optional ninth and highest numbered item).
495 \ Initialize the ACPI option status.
498 str_menu_acpi getenv -1 <> if
499 c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' )
501 arch-i386? if acpipresent? if
503 \ Set menu toggle state to active state
504 \ (required by generic toggle_menuitem)
506 acpienabled? menuacpi @ toggle_stateN !
514 \ Initialize the menu_options visual separator.
517 str_menu_options getenv -1 <> if
518 c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' )
525 \ Initialize "Reboot" menu state variable (prevents double-entry)
526 false menurebootadded !
529 1- menuidx ! \ Initialize the starting index for the menu
530 0 menurow ! \ Initialize the starting position for the menu
532 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8')
534 \ If the "Options:" separator, print it.
535 dup menuoptions @ = if
536 \ Optionally add a reboot option to the menu
537 str_menu_reboot getenv -1 <> if
539 s" Reboot" printmenuitem menureboot !
540 true menurebootadded !
544 menurow @ 2 + menurow !
547 str_menu_optionstext getenv dup -1 <> if
554 \ If this is the ACPI menu option, act accordingly.
556 dup acpimenuitem ( n -- n n c-addr/u | n n -1 )
558 13 +c! ( n n c-addr/u -- n c-addr/u )
561 swap drop ( n n -1 -- n -1 )
562 over menu_command[x] unsetenv
565 \ make sure we have not already initialized this item
566 dup init_stateN dup @ 0= if
569 \ If this menuitem has an initializer, run it
589 \ test for environment variable
591 printmenuitem ( c-addr/u -- n )
600 1+ dup 56 > \ add 1 to iterator, continue if less than 57
604 \ Optionally add a reboot option to the menu
605 menurebootadded @ true <> if
606 str_menu_reboot getenv -1 <> if
607 drop \ no need for the value
608 s" Reboot" \ menu caption (required by printmenuitem)
618 \ Takes a single integer on the stack and updates the timeout display. The
619 \ integer must be between 0 and 9 (we will only update a single digit in the
622 : menu-timeout-update ( N -- )
624 \ Enforce minimum/maximum
625 dup 9 > if drop 9 then
626 dup 0 < if drop 0 then
628 s" Autoboot in N seconds. [Space] to pause" ( n -- n c-addr/u )
631 rot 48 + -rot ( n c-addr/u -- n' c-addr/u ) \ convert to ASCII
632 12 +c! ( n' c-addr/u -- c-addr/u ) \ replace 'N' above
634 menu_timeout_x @ menu_timeout_y @ at-xy \ position cursor
635 type ( c-addr/u -- ) \ print message
637 menu_timeout_x @ menu_timeout_y @ at-xy \ position cursor
638 spaces ( n c-addr/u -- n c-addr ) \ erase message
639 2drop ( n c-addr -- )
642 0 25 at-xy ( position cursor back at bottom-left )
645 \ This function blocks program flow (loops forever) until a key is pressed.
646 \ The key that was pressed is added to the top of the stack in the form of its
647 \ decimal ASCII representation. This function is called by the menu-display
648 \ function. You need not call it directly.
650 : getkey ( -- ascii_keycode )
654 menu_timeout_enabled @ 1 = if
656 seconds ( get current time: -- N )
657 dup menu_time @ <> if ( has time elapsed?: N N N -- N )
659 \ At least 1 second has elapsed since last loop
660 \ so we will decrement our "timeout" (really a
661 \ counter, insuring that we do not proceed too
662 \ fast) and update our timeout display.
664 menu_time ! ( update time record: N -- )
665 menu_timeout @ ( "time" remaining: -- N )
666 dup 0> if ( greater than 0?: N N 0 -- N )
667 1- ( decrement counter: N -- N )
669 ( re-assign: N N Addr -- N )
673 dup 0= swap 0< or if ( N <= 0?: N N -- )
675 0 menu_timeout ! ( 0 Addr -- )
676 0 menu_timeout_enabled ! ( 0 Addr -- )
679 \ update the timer display ( N -- )
680 menu_timeout @ menu-timeout-update
683 \ We've reached the end of the timeout
684 \ (user did not cancel by pressing ANY
687 str_menu_timeout_command getenv dup
696 \ No [detectable] time has elapsed (in seconds)
702 key? if \ Was a key pressed? (see loader(8))
704 \ An actual key was pressed (if the timeout is running,
705 \ kill it regardless of which key was pressed)
706 menu_timeout @ 0<> if
708 0 menu_timeout_enabled !
710 \ clear screen of timeout message
711 0 menu-timeout-update
714 \ get the key that was pressed and exit (if we
715 \ get a non-zero ASCII code)
722 50 ms \ sleep for 50 milliseconds (see loader(8))
727 : menu-erase ( -- ) \ Erases menu and resets positioning variable to positon 1.
729 \ Clear the screen area associated with the interactive menu
731 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
732 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
733 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
734 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
735 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
736 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces
739 \ Reset the starting index and position for the menu
740 menu_start 1- menuidx !
744 \ Erase and redraw the menu. Useful if you change a caption and want to
745 \ update the menu to reflect the new value.
752 \ This function initializes the menu. Call this from your `loader.rc' file
753 \ before calling any other menu-related functions.
757 1- menuidx ! \ Initialize the starting index for the menu
758 0 menurow ! \ Initialize the starting position for the menu
760 \ Assign configuration values
761 str_loader_menu_y getenv dup -1 = if
762 drop \ no custom row position
765 \ make sure custom position is a number
767 menu_default_y \ or use default
771 str_loader_menu_x getenv dup -1 = if
772 drop \ no custom column position
775 \ make sure custom position is a number
777 menu_default_x \ or use default
782 \ Interpret a custom frame type for the menu
783 TRUE ( draw a box? default yes, but might be altered below )
784 str_loader_menu_frame getenv dup -1 = if ( 1 )
785 drop \ no custom frame type
786 else ( 1 ) 2dup s" single" compare-insensitive 0= if ( 2 )
787 f_single ( see frames.4th )
788 else ( 2 ) 2dup s" double" compare-insensitive 0= if ( 3 )
789 f_double ( see frames.4th )
790 else ( 3 ) s" none" compare-insensitive 0= if ( 4 )
791 drop FALSE \ don't draw a box
792 ( 4 ) then ( 3 ) then ( 2 ) then ( 1 ) then
794 42 13 menuX @ 3 - menuY @ 1- box \ Draw frame (w,h,x,y)
797 0 25 at-xy \ Move cursor to the bottom for output
800 \ Main function. Call this from your `loader.rc' file.
802 : menu-display ( -- )
804 0 menu_timeout_enabled ! \ start with automatic timeout disabled
806 \ check indication that automatic execution after delay is requested
807 str_menu_timeout_command getenv -1 <> if ( Addr C -1 -- | Addr )
808 drop ( just testing existence right now: Addr -- )
810 \ initialize state variables
811 seconds menu_time ! ( store the time we started )
812 1 menu_timeout_enabled ! ( enable automatic timeout )
814 \ read custom time-duration (if set)
815 s" autoboot_delay" getenv dup -1 = if
816 drop \ no custom duration (remove dup'd bunk -1)
817 menu_timeout_default \ use default setting
819 2dup ?number 0= if ( if not a number )
820 \ disable timeout if "NO", else use default
821 s" NO" compare-insensitive 0= if
822 0 menu_timeout_enabled !
823 0 ( assigned to menu_timeout below )
830 \ boot immediately if less than zero
839 menu_timeout ! ( store value on stack from above )
841 menu_timeout_enabled @ 1 = if
842 \ read custom column position (if set)
843 str_loader_menu_timeout_x getenv dup -1 = if
844 drop \ no custom column position
845 menu_timeout_default_x \ use default setting
847 \ make sure custom position is a number
849 menu_timeout_default_x \ or use default
852 menu_timeout_x ! ( store value on stack from above )
854 \ read custom row position (if set)
855 str_loader_menu_timeout_y getenv dup -1 = if
856 drop \ no custom row position
857 menu_timeout_default_y \ use default setting
859 \ make sure custom position is a number
861 menu_timeout_default_y \ or use default
864 menu_timeout_y ! ( store value on stack from above )
872 0 25 at-xy \ Move cursor to the bottom for output
873 getkey \ Block here, waiting for a key to be pressed
876 drop exit \ Caught abort (abnormal return)
879 \ Boot if the user pressed Enter/Ctrl-M (13) or
880 \ Ctrl-Enter/Ctrl-J (10)
881 dup over 13 = swap 10 = or if
882 drop ( no longer needed )
884 exit ( pedantic; never reached )
887 dup menureboot @ = if 0 reboot then
889 \ Evaluate the decimal ASCII value against known menu item
890 \ key associations and act accordingly
892 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8')
897 \ Adjust for missing ACPI menuitem on non-i386
898 arch-i386? true <> menuacpi @ 0<> and if
899 menuacpi @ over 2dup < -rot = or
901 ( key >= menuacpi && key < 58: N -- N )
906 \ Test for the environment variable
909 \ Execute the stored procedure
912 \ We expect there to be a non-zero
913 \ value left on the stack after
914 \ executing the stored procedure.
915 \ If so, continue to run, else exit.
922 swap \ need iterator on top
926 \ Re-adjust for missing ACPI menuitem
927 arch-i386? true <> menuacpi @ 0<> and if
929 menuacpi @ 1+ over 2dup < -rot = or
936 swap \ need iterator on top
940 \ Check for menu keycode shortcut(s)
965 1+ dup 56 > \ increment iterator
966 \ continue if less than 57
971 again \ Non-operational key was pressed; repeat
974 \ This function unsets all the possible environment variables associated with
975 \ creating the interactive menu.
979 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8')
981 dup menu_init[x] unsetenv \ menu initializer
982 dup menu_command[x] unsetenv \ menu command
983 dup menu_caption[x] unsetenv \ menu caption
984 dup ansi_caption[x] unsetenv \ ANSI caption
985 dup menu_keycode[x] unsetenv \ menu keycode
986 dup toggled_text[x] unsetenv \ toggle_menuitem caption
987 dup toggled_ansi[x] unsetenv \ toggle_menuitem ANSI caption
989 48 \ Iterator start (inner range 48 to 57; ASCII '0' to '9')
991 \ cycle_menuitem caption and ANSI caption
992 2dup menu_caption[x][y] unsetenv
993 2dup ansi_caption[x][y] unsetenv
996 drop \ inner iterator
998 0 over menukeyN ! \ used by menu-create, menu-display
999 0 over init_stateN ! \ used by menu-create
1000 0 over toggle_stateN ! \ used by toggle_menuitem
1001 0 over init_textN c! \ used by toggle_menuitem
1002 0 over cycle_stateN ! \ used by cycle_menuitem
1004 1+ dup 56 > \ increment, continue if less than 57
1008 str_menu_timeout_command unsetenv \ menu timeout command
1009 str_menu_reboot unsetenv \ Reboot menu option flag
1010 str_menu_acpi unsetenv \ ACPI menu option flag
1011 str_menu_options unsetenv \ Options separator flag
1012 str_menu_optionstext unsetenv \ separator display text
1013 str_menu_init unsetenv \ menu initializer
1020 \ This function both unsets menu variables and visually erases the menu area
1021 \ in-preparation for another menu.
1030 \ Initialize our menu initialization state variables
1040 \ Initialize our boolean state variables
1050 \ Initialize our array state variables
1060 \ Initialize string containers