Annotation of elwix/config/boot/menu.4th, revision 1.3
1.2 misho 1: \ Copyright (c) 2003 Scott Long <scottl@freebsd.org>
2: \ Copyright (c) 2003 Aleksander Fafula <alex@fafula.com>
1.3 ! misho 3: \ Copyright (c) 2006-2012 Devin Teske <dteske@FreeBSD.org>
1.2 misho 4: \ All rights reserved.
5: \
6: \ Redistribution and use in source and binary forms, with or without
7: \ modification, are permitted provided that the following conditions
8: \ are met:
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.
14: \
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
25: \ SUCH DAMAGE.
26: \
1.3 ! misho 27: \ $FreeBSD: src/sys/boot/forth/menu.4th,v 1.13 2012/11/17 04:43:05 svnexp Exp $
1.2 misho 28:
29: marker task-menu.4th
30:
31: \ Frame drawing
32: include /boot/frames.4th
33:
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)
37:
38: 4 constant menu_timeout_default_x \ default column position of timeout
39: 23 constant menu_timeout_default_y \ default row position of timeout msg
40: 10 constant menu_timeout_default \ default timeout (in seconds)
41:
42: \ Customize the following values with care
43:
44: 1 constant menu_start \ Numerical prefix of first menu item
45: dot constant bullet \ Menu bullet (appears after numerical prefix)
46: 5 constant menu_x \ Row position of the menu (from the top)
47: 10 constant menu_y \ Column position of the menu (from left side)
48:
49: \ Menu Appearance
50: variable menuidx \ Menu item stack for number prefixes
51: variable menurow \ Menu item stack for positioning
52: variable menubllt \ Menu item bullet
53:
54: \ Menu Positioning
55: variable menuX \ Menu X offset (columns)
56: variable menuY \ Menu Y offset (rows)
57:
58: \ Menu-item key association/detection
59: variable menukey1
60: variable menukey2
61: variable menukey3
62: variable menukey4
63: variable menukey5
64: variable menukey6
65: variable menukey7
66: variable menukey8
67: variable menureboot
68: variable menurebootadded
69: variable menuacpi
70: variable menuoptions
71:
72: \ Menu timer [count-down] variables
73: variable menu_timeout_enabled \ timeout state (internal use only)
74: variable menu_time \ variable for tracking the passage of time
75: variable menu_timeout \ determined configurable delay duration
76: variable menu_timeout_x \ column position of timeout message
77: variable menu_timeout_y \ row position of timeout message
78:
1.3 ! misho 79: \ Menu initialization status variables
! 80: variable init_state1
! 81: variable init_state2
! 82: variable init_state3
! 83: variable init_state4
! 84: variable init_state5
! 85: variable init_state6
! 86: variable init_state7
! 87: variable init_state8
! 88:
1.2 misho 89: \ Boolean option status variables
90: variable toggle_state1
91: variable toggle_state2
92: variable toggle_state3
93: variable toggle_state4
94: variable toggle_state5
95: variable toggle_state6
96: variable toggle_state7
97: variable toggle_state8
98:
99: \ Array option status variables
100: variable cycle_state1
101: variable cycle_state2
102: variable cycle_state3
103: variable cycle_state4
104: variable cycle_state5
105: variable cycle_state6
106: variable cycle_state7
107: variable cycle_state8
108:
109: \ Containers for storing the initial caption text
110: create init_text1 255 allot
111: create init_text2 255 allot
112: create init_text3 255 allot
113: create init_text4 255 allot
114: create init_text5 255 allot
115: create init_text6 255 allot
116: create init_text7 255 allot
117: create init_text8 255 allot
118:
1.3 ! misho 119: : +c! ( N C-ADDR/U K -- C-ADDR/U )
! 120: 3 pick 3 pick ( n c-addr/u k -- n c-addr/u k n c-addr )
! 121: rot + c! ( n c-addr/u k n c-addr -- n c-addr/u )
! 122: rot drop ( n c-addr/u -- c-addr/u )
! 123: ;
! 124:
! 125: : menukeyN ( N -- ADDR ) s" menukeyN" 7 +c! evaluate ;
! 126: : init_stateN ( N -- ADDR ) s" init_stateN" 10 +c! evaluate ;
! 127: : toggle_stateN ( N -- ADDR ) s" toggle_stateN" 12 +c! evaluate ;
! 128: : cycle_stateN ( N -- ADDR ) s" cycle_stateN" 11 +c! evaluate ;
! 129: : init_textN ( N -- C-ADDR ) s" init_textN" 9 +c! evaluate ;
! 130:
! 131: : str_loader_menu_title ( -- C-ADDR/U ) s" loader_menu_title" ;
! 132: : str_loader_menu_timeout_x ( -- C-ADDR/U ) s" loader_menu_timeout_x" ;
! 133: : str_loader_menu_timeout_y ( -- C-ADDR/U ) s" loader_menu_timeout_y" ;
! 134: : str_menu_init ( -- C-ADDR/U ) s" menu_init" ;
! 135: : str_menu_timeout_command ( -- C-ADDR/U ) s" menu_timeout_command" ;
! 136: : str_menu_reboot ( -- C-ADDR/U ) s" menu_reboot" ;
! 137: : str_menu_acpi ( -- C-ADDR/U ) s" menu_acpi" ;
! 138: : str_menu_options ( -- C-ADDR/U ) s" menu_options" ;
! 139: : str_menu_optionstext ( -- C-ADDR/U ) s" menu_optionstext" ;
! 140:
! 141: : str_menu_init[x] ( -- C-ADDR/U ) s" menu_init[x]" ;
! 142: : str_menu_command[x] ( -- C-ADDR/U ) s" menu_command[x]" ;
! 143: : str_menu_caption[x] ( -- C-ADDR/U ) s" menu_caption[x]" ;
! 144: : str_ansi_caption[x] ( -- C-ADDR/U ) s" ansi_caption[x]" ;
! 145: : str_menu_keycode[x] ( -- C-ADDR/U ) s" menu_keycode[x]" ;
! 146: : str_toggled_text[x] ( -- C-ADDR/U ) s" toggled_text[x]" ;
! 147: : str_toggled_ansi[x] ( -- C-ADDR/U ) s" toggled_ansi[x]" ;
! 148: : str_menu_caption[x][y] ( -- C-ADDR/U ) s" menu_caption[x][y]" ;
! 149: : str_ansi_caption[x][y] ( -- C-ADDR/U ) s" ansi_caption[x][y]" ;
! 150:
! 151: : menu_init[x] ( N -- C-ADDR/U ) str_menu_init[x] 10 +c! ;
! 152: : menu_command[x] ( N -- C-ADDR/U ) str_menu_command[x] 13 +c! ;
! 153: : menu_caption[x] ( N -- C-ADDR/U ) str_menu_caption[x] 13 +c! ;
! 154: : ansi_caption[x] ( N -- C-ADDR/U ) str_ansi_caption[x] 13 +c! ;
! 155: : menu_keycode[x] ( N -- C-ADDR/U ) str_menu_keycode[x] 13 +c! ;
! 156: : toggled_text[x] ( N -- C-ADDR/U ) str_toggled_text[x] 13 +c! ;
! 157: : toggled_ansi[x] ( N -- C-ADDR/U ) str_toggled_ansi[x] 13 +c! ;
! 158: : menu_caption[x][y] ( N M -- C-ADDR/U ) str_menu_caption[x][y] 16 +c! 13 +c! ;
! 159: : ansi_caption[x][y] ( N M -- C-ADDR/U ) str_ansi_caption[x][y] 16 +c! 13 +c! ;
! 160:
1.2 misho 161: : arch-i386? ( -- BOOL ) \ Returns TRUE (-1) on i386, FALSE (0) otherwise.
162: s" arch-i386" environment? dup if
163: drop
164: then
165: ;
166:
167: \ This function prints a menu item at menuX (row) and menuY (column), returns
168: \ the incremental decimal ASCII value associated with the menu item, and
169: \ increments the cursor position to the next row for the creation of the next
170: \ menu item. This function is called by the menu-create function. You need not
171: \ call it directly.
172: \
173: : printmenuitem ( menu_item_str -- ascii_keycode )
174:
175: menurow dup @ 1+ swap ! ( increment menurow )
176: menuidx dup @ 1+ swap ! ( increment menuidx )
177:
178: \ Calculate the menuitem row position
179: menurow @ menuY @ +
180:
181: \ Position the cursor at the menuitem position
182: dup menuX @ swap at-xy
183:
184: \ Print the value of menuidx
185: loader_color? if
1.3 ! misho 186: ." [1m" ( [22m )
1.2 misho 187: then
188: menuidx @ .
189: loader_color? if
1.3 ! misho 190: ." [37m" ( [39m )
1.2 misho 191: then
192:
193: \ Move the cursor forward 1 column
194: dup menuX @ 1+ swap at-xy
195:
196: menubllt @ emit \ Print the menu bullet using the emit function
197:
198: \ Move the cursor to the 3rd column from the current position
199: \ to allow for a space between the numerical prefix and the
200: \ text caption
201: menuX @ 3 + swap at-xy
202:
203: \ Print the menu caption (we expect a string to be on the stack
204: \ prior to invoking this function)
205: type
206:
207: \ Here we will add the ASCII decimal of the numerical prefix
208: \ to the stack (decimal ASCII for `1' is 49) as a "return value"
209: menuidx @ 48 +
210: ;
211:
212: : toggle_menuitem ( N -- N ) \ toggles caption text and internal menuitem state
213:
214: \ ASCII numeral equal to user-selected menu item must be on the stack.
215: \ We do not modify the stack, so the ASCII numeral is left on top.
216:
1.3 ! misho 217: dup init_textN c@ 0= if
1.2 misho 218: \ NOTE: no need to check toggle_stateN since the first time we
219: \ are called, we will populate init_textN. Further, we don't
220: \ need to test whether menu_caption[x] (ansi_caption[x] when
221: \ loader_color=1) is available since we would not have been
222: \ called if the caption was NULL.
223:
224: \ base name of environment variable
1.3 ! misho 225: dup ( n -- n n ) \ key pressed
1.2 misho 226: loader_color? if
1.3 ! misho 227: ansi_caption[x]
1.2 misho 228: else
1.3 ! misho 229: menu_caption[x]
1.2 misho 230: then
231: getenv dup -1 <> if
232:
1.3 ! misho 233: 2 pick ( n c-addr/u -- n c-addr/u n )
! 234: init_textN ( n c-addr/u n -- n c-addr/u c-addr )
1.2 misho 235:
236: \ now we have the buffer c-addr on top
237: \ ( followed by c-addr/u of current caption )
238:
239: \ Copy the current caption into our buffer
240: 2dup c! -rot \ store strlen at first byte
241: begin
242: rot 1+ \ bring alt addr to top and increment
243: -rot -rot \ bring buffer addr to top
244: 2dup c@ swap c! \ copy current character
245: 1+ \ increment buffer addr
246: rot 1- \ bring buffer len to top and decrement
247: dup 0= \ exit loop if buffer len is zero
248: until
249: 2drop \ buffer len/addr
250: drop \ alt addr
251:
252: else
253: drop
254: then
255: then
256:
257: \ Now we are certain to have init_textN populated with the initial
258: \ value of menu_caption[x] (ansi_caption[x] with loader_color enabled).
259: \ We can now use init_textN as the untoggled caption and
260: \ toggled_text[x] (toggled_ansi[x] with loader_color enabled) as the
261: \ toggled caption and store the appropriate value into menu_caption[x]
262: \ (again, ansi_caption[x] with loader_color enabled). Last, we'll
263: \ negate the toggled state so that we reverse the flow on subsequent
264: \ calls.
265:
1.3 ! misho 266: dup toggle_stateN @ 0= if
1.2 misho 267: \ state is OFF, toggle to ON
268:
1.3 ! misho 269: dup ( n -- n n ) \ key pressed
1.2 misho 270: loader_color? if
1.3 ! misho 271: toggled_ansi[x]
1.2 misho 272: else
1.3 ! misho 273: toggled_text[x]
1.2 misho 274: then
275: getenv dup -1 <> if
276: \ Assign toggled text to menu caption
1.3 ! misho 277: 2 pick ( n c-addr/u -- n c-addr/u n ) \ key pressed
1.2 misho 278: loader_color? if
1.3 ! misho 279: ansi_caption[x]
1.2 misho 280: else
1.3 ! misho 281: menu_caption[x]
1.2 misho 282: then
1.3 ! misho 283: setenv
1.2 misho 284: else
285: \ No toggled text, keep the same caption
1.3 ! misho 286: drop ( n -1 -- n ) \ getenv cruft
1.2 misho 287: then
288:
289: true \ new value of toggle state var (to be stored later)
290: else
291: \ state is ON, toggle to OFF
292:
1.3 ! misho 293: dup init_textN count ( n -- n c-addr/u )
1.2 misho 294:
1.3 ! misho 295: \ Assign init_textN text to menu caption
! 296: 2 pick ( n c-addr/u -- n c-addr/u n ) \ key pressed
1.2 misho 297: loader_color? if
1.3 ! misho 298: ansi_caption[x]
1.2 misho 299: else
1.3 ! misho 300: menu_caption[x]
1.2 misho 301: then
1.3 ! misho 302: setenv
1.2 misho 303:
1.3 ! misho 304: false \ new value of toggle state var (to be stored below)
1.2 misho 305: then
306:
307: \ now we'll store the new toggle state (on top of stack)
1.3 ! misho 308: over toggle_stateN !
1.2 misho 309: ;
310:
311: : cycle_menuitem ( N -- N ) \ cycles through array of choices for a menuitem
312:
313: \ ASCII numeral equal to user-selected menu item must be on the stack.
314: \ We do not modify the stack, so the ASCII numeral is left on top.
315:
1.3 ! misho 316: dup cycle_stateN dup @ 1+ \ get value and increment
1.2 misho 317:
318: \ Before assigning the (incremented) value back to the pointer,
319: \ let's test for the existence of this particular array element.
320: \ If the element exists, we'll store index value and move on.
321: \ Otherwise, we'll loop around to zero and store that.
322:
1.3 ! misho 323: dup 48 + ( n addr k -- n addr k k' )
! 324: \ duplicate array index and convert to ASCII numeral
1.2 misho 325:
1.3 ! misho 326: 3 pick swap ( n addr k k' -- n addr k n k' ) \ (n,k') as (x,y)
1.2 misho 327: loader_color? if
1.3 ! misho 328: ansi_caption[x][y]
1.2 misho 329: else
1.3 ! misho 330: menu_caption[x][y]
1.2 misho 331: then
1.3 ! misho 332: ( n addr k n k' -- n addr k c-addr/u )
1.2 misho 333:
334: \ Now test for the existence of our incremented array index in the
335: \ form of $menu_caption[x][y] ($ansi_caption[x][y] with loader_color
336: \ enabled) as set in loader.rc(5), et. al.
337:
338: getenv dup -1 = if
339: \ No caption set for this array index. Loop back to zero.
340:
1.3 ! misho 341: drop ( n addr k -1 -- n addr k ) \ getenv cruft
! 342: drop 0 ( n addr k -- n addr 0 ) \ new value to store later
1.2 misho 343:
1.3 ! misho 344: 2 pick [char] 0 ( n addr 0 -- n addr 0 n 48 ) \ (n,48) as (x,y)
1.2 misho 345: loader_color? if
1.3 ! misho 346: ansi_caption[x][y]
1.2 misho 347: else
1.3 ! misho 348: menu_caption[x][y]
1.2 misho 349: then
1.3 ! misho 350: ( n addr 0 n 48 -- n addr 0 c-addr/u )
1.2 misho 351: getenv dup -1 = if
352: \ This is highly unlikely to occur, but to make
353: \ sure that things move along smoothly, allocate
354: \ a temporary NULL string
355:
1.3 ! misho 356: drop ( n addr 0 -1 -- n addr 0 ) \ getenv cruft
! 357: s" " ( n addr 0 -- n addr 0 c-addr/u )
1.2 misho 358: then
359: then
360:
361: \ At this point, we should have the following on the stack (in order,
362: \ from bottom to top):
363: \
1.3 ! misho 364: \ n - Ascii numeral representing the menu choice (inherited)
! 365: \ addr - address of our internal cycle_stateN variable
! 366: \ k - zero-based number we intend to store to the above
! 367: \ c-addr/u - string value we intend to store to menu_caption[x]
! 368: \ (or ansi_caption[x] with loader_color enabled)
1.2 misho 369: \
370: \ Let's perform what we need to with the above.
371:
1.3 ! misho 372: \ Assign array value text to menu caption
! 373: 4 pick ( n addr k c-addr/u -- n addr k c-addr/u n )
1.2 misho 374: loader_color? if
1.3 ! misho 375: ansi_caption[x]
1.2 misho 376: else
1.3 ! misho 377: menu_caption[x]
1.2 misho 378: then
1.3 ! misho 379: setenv
1.2 misho 380:
1.3 ! misho 381: swap ! ( n addr k -- n ) \ update array state variable
1.2 misho 382: ;
383:
384: : acpipresent? ( -- flag ) \ Returns TRUE if ACPI is present, FALSE otherwise
385: s" hint.acpi.0.rsdp" getenv
386: dup -1 = if
387: drop false exit
388: then
389: 2drop
390: true
391: ;
392:
393: : acpienabled? ( -- flag ) \ Returns TRUE if ACPI is enabled, FALSE otherwise
394: s" hint.acpi.0.disabled" getenv
395: dup -1 <> if
396: s" 0" compare 0<> if
397: false exit
398: then
399: else
400: drop
401: then
402: true
403: ;
404:
405: \ This function prints the appropriate menuitem basename to the stack if an
406: \ ACPI option is to be presented to the user, otherwise returns -1. Used
407: \ internally by menu-create, you need not (nor should you) call this directly.
408: \
1.3 ! misho 409: : acpimenuitem ( -- C-Addr/U | -1 )
1.2 misho 410:
411: arch-i386? if
412: acpipresent? if
413: acpienabled? if
414: loader_color? if
1.3 ! misho 415: str_toggled_ansi[x]
1.2 misho 416: else
1.3 ! misho 417: str_toggled_text[x]
1.2 misho 418: then
419: else
420: loader_color? if
1.3 ! misho 421: str_ansi_caption[x]
1.2 misho 422: else
1.3 ! misho 423: str_menu_caption[x]
1.2 misho 424: then
425: then
426: else
427: menuidx dup @ 1+ swap ! ( increment menuidx )
428: -1
429: then
430: else
431: -1
432: then
433: ;
434:
435: \ This function creates the list of menu items. This function is called by the
436: \ menu-display function. You need not be call it directly.
437: \
438: : menu-create ( -- )
439:
440: \ Print the frame caption at (x,y)
1.3 ! misho 441: str_loader_menu_title getenv dup -1 = if
1.2 misho 442: drop s" Welcome to -ELWIX-"
443: then
444: 24 over 2 / - 9 at-xy type
445:
1.3 ! misho 446: \ If $menu_init is set, evaluate it (allowing for whole menus to be
! 447: \ constructed dynamically -- as this function could conceivably set
! 448: \ the remaining environment variables to construct the menu entirely).
! 449: \
! 450: str_menu_init getenv dup -1 <> if
! 451: evaluate
! 452: else
! 453: drop
! 454: then
! 455:
1.2 misho 456: \ Print our menu options with respective key/variable associations.
457: \ `printmenuitem' ends by adding the decimal ASCII value for the
458: \ numerical prefix to the stack. We store the value left on the stack
459: \ to the key binding variable for later testing against a character
460: \ captured by the `getkey' function.
461:
462: \ Note that any menu item beyond 9 will have a numerical prefix on the
463: \ screen consisting of the first digit (ie. 1 for the tenth menu item)
464: \ and the key required to activate that menu item will be the decimal
465: \ ASCII of 48 plus the menu item (ie. 58 for the tenth item, aka. `:')
466: \ which is misleading and not desirable.
467: \
468: \ Thus, we do not allow more than 8 configurable items on the menu
469: \ (with "Reboot" as the optional ninth and highest numbered item).
470:
471: \
472: \ Initialize the ACPI option status.
473: \
474: 0 menuacpi !
1.3 ! misho 475: str_menu_acpi getenv -1 <> if
1.2 misho 476: c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' )
477: menuacpi !
478: arch-i386? if acpipresent? if
479: \
480: \ Set menu toggle state to active state
481: \ (required by generic toggle_menuitem)
482: \
1.3 ! misho 483: acpienabled? menuacpi @ toggle_stateN !
1.2 misho 484: then then
485: else
486: drop
487: then
488: then
489:
490: \
491: \ Initialize the menu_options visual separator.
492: \
493: 0 menuoptions !
1.3 ! misho 494: str_menu_options getenv -1 <> if
1.2 misho 495: c@ dup 48 > over 57 < and if ( '1' <= c1 <= '8' )
496: menuoptions !
497: else
498: drop
499: then
500: then
501:
502: \ Initialize "Reboot" menu state variable (prevents double-entry)
503: false menurebootadded !
504:
1.3 ! misho 505: menu_start
! 506: 1- menuidx ! \ Initialize the starting index for the menu
! 507: 0 menurow ! \ Initialize the starting position for the menu
! 508:
1.2 misho 509: 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8')
510: begin
511: \ If the "Options:" separator, print it.
512: dup menuoptions @ = if
513: \ Optionally add a reboot option to the menu
1.3 ! misho 514: str_menu_reboot getenv -1 <> if
1.2 misho 515: drop
516: s" Reboot" printmenuitem menureboot !
517: true menurebootadded !
518: then
519:
520: menuX @
521: menurow @ 2 + menurow !
522: menurow @ menuY @ +
523: at-xy
1.3 ! misho 524: str_menu_optionstext getenv dup -1 <> if
! 525: type
! 526: else
! 527: drop ." Options:"
! 528: then
1.2 misho 529: then
530:
531: \ If this is the ACPI menu option, act accordingly.
532: dup menuacpi @ = if
1.3 ! misho 533: dup acpimenuitem ( n -- n n c-addr/u | n n -1 )
! 534: dup -1 <> if
! 535: 13 +c! ( n n c-addr/u -- n c-addr/u )
! 536: \ replace 'x' with n
! 537: else
! 538: swap drop ( n n -1 -- n -1 )
! 539: over menu_command[x] unsetenv
! 540: then
1.2 misho 541: else
1.3 ! misho 542: \ make sure we have not already initialized this item
! 543: dup init_stateN dup @ 0= if
! 544: 1 swap !
! 545:
! 546: \ If this menuitem has an initializer, run it
! 547: dup menu_init[x]
! 548: getenv dup -1 <> if
! 549: evaluate
! 550: else
! 551: drop
! 552: then
! 553: else
! 554: drop
! 555: then
! 556:
! 557: dup
1.2 misho 558: loader_color? if
1.3 ! misho 559: ansi_caption[x]
1.2 misho 560: else
1.3 ! misho 561: menu_caption[x]
1.2 misho 562: then
563: then
564:
565: dup -1 <> if
566: \ test for environment variable
567: getenv dup -1 <> if
1.3 ! misho 568: printmenuitem ( c-addr/u -- n )
! 569: dup menukeyN !
1.2 misho 570: else
571: drop
572: then
573: else
574: drop
575: then
576:
577: 1+ dup 56 > \ add 1 to iterator, continue if less than 57
578: until
579: drop \ iterator
580:
581: \ Optionally add a reboot option to the menu
582: menurebootadded @ true <> if
1.3 ! misho 583: str_menu_reboot getenv -1 <> if
1.2 misho 584: drop \ no need for the value
585: s" Reboot" \ menu caption (required by printmenuitem)
586:
587: printmenuitem
588: menureboot !
589: else
590: 0 menureboot !
591: then
592: then
593: ;
594:
595: \ Takes a single integer on the stack and updates the timeout display. The
596: \ integer must be between 0 and 9 (we will only update a single digit in the
597: \ source message).
598: \
599: : menu-timeout-update ( N -- )
600:
1.3 ! misho 601: \ Enforce minimum/maximum
! 602: dup 9 > if drop 9 then
! 603: dup 0 < if drop 0 then
! 604:
! 605: s" Autoboot in N seconds. [Space] to pause" ( n -- n c-addr/u )
! 606:
! 607: 2 pick 0> if
! 608: rot 48 + -rot ( n c-addr/u -- n' c-addr/u ) \ convert to ASCII
! 609: 12 +c! ( n' c-addr/u -- c-addr/u ) \ replace 'N' above
1.2 misho 610:
1.3 ! misho 611: menu_timeout_x @ menu_timeout_y @ at-xy \ position cursor
! 612: type ( c-addr/u -- ) \ print message
! 613: else
! 614: menu_timeout_x @ menu_timeout_y @ at-xy \ position cursor
! 615: spaces ( n c-addr/u -- n c-addr ) \ erase message
! 616: 2drop ( n c-addr -- )
1.2 misho 617: then
618:
619: 0 25 at-xy ( position cursor back at bottom-left )
620: ;
621:
622: \ This function blocks program flow (loops forever) until a key is pressed.
623: \ The key that was pressed is added to the top of the stack in the form of its
624: \ decimal ASCII representation. This function is called by the menu-display
625: \ function. You need not call it directly.
626: \
627: : getkey ( -- ascii_keycode )
628:
629: begin \ loop forever
630:
631: menu_timeout_enabled @ 1 = if
632: ( -- )
633: seconds ( get current time: -- N )
634: dup menu_time @ <> if ( has time elapsed?: N N N -- N )
635:
636: \ At least 1 second has elapsed since last loop
637: \ so we will decrement our "timeout" (really a
638: \ counter, insuring that we do not proceed too
639: \ fast) and update our timeout display.
640:
641: menu_time ! ( update time record: N -- )
642: menu_timeout @ ( "time" remaining: -- N )
643: dup 0> if ( greater than 0?: N N 0 -- N )
644: 1- ( decrement counter: N -- N )
645: dup menu_timeout !
646: ( re-assign: N N Addr -- N )
647: then
648: ( -- N )
649:
650: dup 0= swap 0< or if ( N <= 0?: N N -- )
651: \ halt the timer
652: 0 menu_timeout ! ( 0 Addr -- )
653: 0 menu_timeout_enabled ! ( 0 Addr -- )
654: then
655:
656: \ update the timer display ( N -- )
657: menu_timeout @ menu-timeout-update
658:
659: menu_timeout @ 0= if
660: \ We've reached the end of the timeout
661: \ (user did not cancel by pressing ANY
662: \ key)
663:
1.3 ! misho 664: str_menu_timeout_command getenv dup
1.2 misho 665: -1 = if
666: drop \ clean-up
667: else
668: evaluate
669: then
670: then
671:
672: else ( -- N )
673: \ No [detectable] time has elapsed (in seconds)
674: drop ( N -- )
675: then
676: ( -- )
677: then
678:
679: key? if \ Was a key pressed? (see loader(8))
680:
681: \ An actual key was pressed (if the timeout is running,
682: \ kill it regardless of which key was pressed)
683: menu_timeout @ 0<> if
684: 0 menu_timeout !
685: 0 menu_timeout_enabled !
686:
687: \ clear screen of timeout message
688: 0 menu-timeout-update
689: then
690:
691: \ get the key that was pressed and exit (if we
692: \ get a non-zero ASCII code)
693: key dup 0<> if
694: exit
695: else
696: drop
697: then
698: then
699: 50 ms \ sleep for 50 milliseconds (see loader(8))
700:
701: again
702: ;
703:
704: : menu-erase ( -- ) \ Erases menu and resets positioning variable to positon 1.
705:
706: \ Clear the screen area associated with the interactive menu
707: menuX @ menuY @
708: 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
709: 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
710: 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
711: 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
712: 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces 1+
713: 2dup at-xy 38 spaces 1+ 2dup at-xy 38 spaces
714: 2drop
715:
716: \ Reset the starting index and position for the menu
717: menu_start 1- menuidx !
718: 0 menurow !
719: ;
720:
721: \ Erase and redraw the menu. Useful if you change a caption and want to
722: \ update the menu to reflect the new value.
723: \
724: : menu-redraw ( -- )
725: menu-erase
726: menu-create
727: ;
728:
729: \ This function initializes the menu. Call this from your `loader.rc' file
730: \ before calling any other menu-related functions.
731: \
732: : menu-init ( -- )
733: menu_start
734: 1- menuidx ! \ Initialize the starting index for the menu
735: 0 menurow ! \ Initialize the starting position for the menu
736: 42 13 2 9 box \ Draw frame (w,h,x,y)
737: 0 25 at-xy \ Move cursor to the bottom for output
738: ;
739:
740: \ Main function. Call this from your `loader.rc' file.
741: \
742: : menu-display ( -- )
743:
744: 0 menu_timeout_enabled ! \ start with automatic timeout disabled
745:
746: \ check indication that automatic execution after delay is requested
1.3 ! misho 747: str_menu_timeout_command getenv -1 <> if ( Addr C -1 -- | Addr )
1.2 misho 748: drop ( just testing existence right now: Addr -- )
749:
750: \ initialize state variables
751: seconds menu_time ! ( store the time we started )
752: 1 menu_timeout_enabled ! ( enable automatic timeout )
753:
754: \ read custom time-duration (if set)
755: s" autoboot_delay" getenv dup -1 = if
756: drop \ no custom duration (remove dup'd bunk -1)
757: menu_timeout_default \ use default setting
758: else
759: 2dup ?number 0= if ( if not a number )
760: \ disable timeout if "NO", else use default
761: s" NO" compare-insensitive 0= if
762: 0 menu_timeout_enabled !
763: 0 ( assigned to menu_timeout below )
764: else
765: menu_timeout_default
766: then
767: else
768: -rot 2drop
769:
770: \ boot immediately if less than zero
771: dup 0< if
772: drop
773: menu-create
774: 0 25 at-xy
775: 0 boot
776: then
777: then
778: then
779: menu_timeout ! ( store value on stack from above )
780:
781: menu_timeout_enabled @ 1 = if
782: \ read custom column position (if set)
1.3 ! misho 783: str_loader_menu_timeout_x getenv dup -1 = if
1.2 misho 784: drop \ no custom column position
785: menu_timeout_default_x \ use default setting
786: else
787: \ make sure custom position is a number
788: ?number 0= if
789: menu_timeout_default_x \ or use default
790: then
791: then
792: menu_timeout_x ! ( store value on stack from above )
793:
794: \ read custom row position (if set)
1.3 ! misho 795: str_loader_menu_timeout_y getenv dup -1 = if
1.2 misho 796: drop \ no custom row position
797: menu_timeout_default_y \ use default setting
798: else
799: \ make sure custom position is a number
800: ?number 0= if
801: menu_timeout_default_y \ or use default
802: then
803: then
804: menu_timeout_y ! ( store value on stack from above )
805: then
806: then
807:
808: menu-create
809:
810: begin \ Loop forever
811:
812: 0 25 at-xy \ Move cursor to the bottom for output
813: getkey \ Block here, waiting for a key to be pressed
814:
815: dup -1 = if
816: drop exit \ Caught abort (abnormal return)
817: then
818:
819: \ Boot if the user pressed Enter/Ctrl-M (13) or
820: \ Ctrl-Enter/Ctrl-J (10)
821: dup over 13 = swap 10 = or if
822: drop ( no longer needed )
823: s" boot" evaluate
824: exit ( pedantic; never reached )
825: then
826:
1.3 ! misho 827: dup menureboot @ = if 0 reboot then
! 828:
1.2 misho 829: \ Evaluate the decimal ASCII value against known menu item
830: \ key associations and act accordingly
831:
832: 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8')
833: begin
1.3 ! misho 834: dup menukeyN @
! 835: rot tuck = if
1.2 misho 836:
837: \ Adjust for missing ACPI menuitem on non-i386
838: arch-i386? true <> menuacpi @ 0<> and if
839: menuacpi @ over 2dup < -rot = or
840: over 58 < and if
841: ( key >= menuacpi && key < 58: N -- N )
842: 1+
843: then
844: then
845:
846: \ Test for the environment variable
1.3 ! misho 847: dup menu_command[x]
1.2 misho 848: getenv dup -1 <> if
849: \ Execute the stored procedure
850: evaluate
851:
852: \ We expect there to be a non-zero
853: \ value left on the stack after
854: \ executing the stored procedure.
855: \ If so, continue to run, else exit.
856:
857: 0= if
858: drop \ key pressed
859: drop \ loop iterator
860: exit
861: else
862: swap \ need iterator on top
863: then
864: then
865:
866: \ Re-adjust for missing ACPI menuitem
867: arch-i386? true <> menuacpi @ 0<> and if
868: swap
869: menuacpi @ 1+ over 2dup < -rot = or
870: over 59 < and if
871: 1-
872: then
873: swap
874: then
875: else
876: swap \ need iterator on top
877: then
878:
879: \
880: \ Check for menu keycode shortcut(s)
881: \
1.3 ! misho 882: dup menu_keycode[x]
1.2 misho 883: getenv dup -1 = if
884: drop
885: else
886: ?number 0<> if
887: rot tuck = if
888: swap
1.3 ! misho 889: dup menu_command[x]
1.2 misho 890: getenv dup -1 <> if
891: evaluate
892: 0= if
893: 2drop
894: exit
895: then
896: else
897: drop
898: then
899: else
900: swap
901: then
902: then
903: then
904:
905: 1+ dup 56 > \ increment iterator
906: \ continue if less than 57
907: until
908: drop \ loop iterator
1.3 ! misho 909: drop \ key pressed
1.2 misho 910:
911: again \ Non-operational key was pressed; repeat
912: ;
913:
914: \ This function unsets all the possible environment variables associated with
1.3 ! misho 915: \ creating the interactive menu.
1.2 misho 916: \
1.3 ! misho 917: : menu-unset ( -- )
1.2 misho 918:
919: 49 \ Iterator start (loop range 49 to 56; ASCII '1' to '8')
920: begin
1.3 ! misho 921: dup menu_init[x] unsetenv \ menu initializer
! 922: dup menu_command[x] unsetenv \ menu command
! 923: dup menu_caption[x] unsetenv \ menu caption
! 924: dup ansi_caption[x] unsetenv \ ANSI caption
! 925: dup menu_keycode[x] unsetenv \ menu keycode
! 926: dup toggled_text[x] unsetenv \ toggle_menuitem caption
! 927: dup toggled_ansi[x] unsetenv \ toggle_menuitem ANSI caption
! 928:
! 929: 48 \ Iterator start (inner range 48 to 57; ASCII '0' to '9')
! 930: begin
! 931: \ cycle_menuitem caption and ANSI caption
! 932: 2dup menu_caption[x][y] unsetenv
! 933: 2dup ansi_caption[x][y] unsetenv
! 934: 1+ dup 57 >
! 935: until
! 936: drop \ inner iterator
1.2 misho 937:
1.3 ! misho 938: 0 over menukeyN ! \ used by menu-create, menu-display
! 939: 0 over init_stateN ! \ used by menu-create
! 940: 0 over toggle_stateN ! \ used by toggle_menuitem
! 941: 0 over init_textN c! \ used by toggle_menuitem
! 942: 0 over cycle_stateN ! \ used by cycle_menuitem
1.2 misho 943:
944: 1+ dup 56 > \ increment, continue if less than 57
945: until
946: drop \ iterator
947:
1.3 ! misho 948: str_menu_timeout_command unsetenv \ menu timeout command
! 949: str_menu_reboot unsetenv \ Reboot menu option flag
! 950: str_menu_acpi unsetenv \ ACPI menu option flag
! 951: str_menu_options unsetenv \ Options separator flag
! 952: str_menu_optionstext unsetenv \ separator display text
! 953: str_menu_init unsetenv \ menu initializer
! 954:
1.2 misho 955: 0 menureboot !
956: 0 menuacpi !
957: 0 menuoptions !
1.3 ! misho 958: ;
1.2 misho 959:
1.3 ! misho 960: \ This function both unsets menu variables and visually erases the menu area
! 961: \ in-preparation for another menu.
! 962: \
! 963: : menu-clear ( -- )
! 964: menu-unset
1.2 misho 965: menu-erase
966: ;
967:
968: \ Assign configuration values
969: bullet menubllt !
970: 10 menuY !
971: 5 menuX !
972:
1.3 ! misho 973: \ Initialize our menu initialization state variables
! 974: 0 init_state1 !
! 975: 0 init_state2 !
! 976: 0 init_state3 !
! 977: 0 init_state4 !
! 978: 0 init_state5 !
! 979: 0 init_state6 !
! 980: 0 init_state7 !
! 981: 0 init_state8 !
! 982:
1.2 misho 983: \ Initialize our boolean state variables
984: 0 toggle_state1 !
985: 0 toggle_state2 !
986: 0 toggle_state3 !
987: 0 toggle_state4 !
988: 0 toggle_state5 !
989: 0 toggle_state6 !
990: 0 toggle_state7 !
991: 0 toggle_state8 !
992:
993: \ Initialize our array state variables
994: 0 cycle_state1 !
995: 0 cycle_state2 !
996: 0 cycle_state3 !
997: 0 cycle_state4 !
998: 0 cycle_state5 !
999: 0 cycle_state6 !
1000: 0 cycle_state7 !
1001: 0 cycle_state8 !
1002:
1003: \ Initialize string containers
1004: 0 init_text1 c!
1005: 0 init_text2 c!
1006: 0 init_text3 c!
1007: 0 init_text4 c!
1008: 0 init_text5 c!
1009: 0 init_text6 c!
1010: 0 init_text7 c!
1011: 0 init_text8 c!
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>