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