home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / basic / menu.bas < prev    next >
Encoding:
BASIC Source File  |  1989-11-09  |  46.9 KB  |  1,276 lines

  1. '============================================================================
  2. '
  3. '     MENU.BAS - Pull-down Menu Routines for the User Interface Toolbox in
  4. '           Microsoft BASIC 7.0, Professional Development System
  5. '              Copyright (C) 1987-1989, Microsoft Corporation
  6. '
  7. '  NOTE:    This sample source code toolbox is intended to demonstrate some
  8. '           of the extended capabilities of Microsoft BASIC 7.0 Professional
  9. '           Development system that can help to leverage the professional
  10. '           developer's time more effectively.  While you are free to use,
  11. '           modify, or distribute the routines in this module in any way you
  12. '           find useful, it should be noted that these are examples only and
  13. '           should not be relied upon as a fully-tested "add-on" library.
  14. '
  15. '  PURPOSE: These are the routines which provide support for the pull-down
  16. '           menus in the user interface toolbox.
  17. '
  18. '  For information on creating a library and QuickLib from the routines
  19. '  contained in this file, read the comment header of GENERAL.BAS.
  20. '
  21. '============================================================================
  22.  
  23. DEFINT A-Z
  24.  
  25. '$INCLUDE: 'general.bi'
  26. '$INCLUDE: 'mouse.bi'
  27. '$INCLUDE: 'menu.bi'
  28.  
  29. COMMON SHARED /uitools/ GloMenu    AS MenuMiscType
  30. COMMON SHARED /uitools/ GloTitle() AS MenuTitleType
  31. COMMON SHARED /uitools/ GloItem()  AS MenuItemType
  32.  
  33. FUNCTION MenuCheck (action%) STATIC
  34.  
  35.     SELECT CASE action
  36.  
  37.     '=======================================================================
  38.     ' This simulates "polling" for a menu event.  If a menu event occured,
  39.     ' GloMenu.currMenu and .currItem are set.  When MenuCheck(0) is
  40.     ' called, these values are transfered to .lastMenu and .lastItem.
  41.     ' MenuCheck(0) then returns the menu number, or 0 (FALSE) if none
  42.     ' selected as of last call
  43.     '=======================================================================
  44.  
  45.         CASE 0
  46.             GloMenu.lastMenu = GloMenu.currMenu
  47.             GloMenu.lastItem = GloMenu.currItem
  48.             GloMenu.currMenu = 0
  49.             GloMenu.currItem = 0
  50.             MenuCheck = GloMenu.lastMenu
  51.  
  52.         '===================================================================
  53.         ' Returns the menu item last selected.  Functions only after a call
  54.         ' to MenuCheck(0)
  55.         '===================================================================
  56.  
  57.         CASE 1
  58.             MenuCheck = GloMenu.lastItem
  59.  
  60.         '===================================================================
  61.         ' Checks GloMenu.currMenu and .currItem.  If both are not 0, this
  62.         ' returns TRUE meaning a menu has been selected since MenuCheck(0)
  63.         ' was last called.  This does not change any values, it simply
  64.         ' reports on the current state.
  65.         '===================================================================
  66.  
  67.         CASE 2
  68.             IF GloMenu.currMenu = 0 OR GloMenu.currItem = 0 THEN
  69.                 MenuCheck = FALSE
  70.             ELSE
  71.                 MenuCheck = TRUE
  72.             END IF
  73.         CASE ELSE
  74.             MenuCheck = 0
  75.     END SELECT
  76.  
  77. END FUNCTION
  78.  
  79. SUB MenuColor (fore, back, highlight, disabled, cursorFore, cursorBack, cursorHi)
  80.  
  81.     GloMenu.fore = fore
  82.     GloMenu.back = back
  83.     GloMenu.highlight = highlight
  84.     GloMenu.disabled = disabled
  85.     GloMenu.cursorFore = cursorFore
  86.     GloMenu.cursorBack = cursorBack
  87.     GloMenu.cursorHi = cursorHi
  88.  
  89. END SUB
  90.  
  91. SUB MenuDo STATIC
  92.  
  93.     '=======================================================================
  94.     ' If menu event trapping turned off, return immediately
  95.     '=======================================================================
  96.  
  97.     IF NOT GloMenu.MenuOn THEN
  98.         EXIT SUB
  99.     END IF
  100.  
  101.     '=======================================================================
  102.     ' Initialize MenuDo's variables, and then enter the main loop
  103.     '=======================================================================
  104.  
  105.     GOSUB MenuDoInit
  106.  
  107.     WHILE NOT MenuDoDone
  108.  
  109.         '===================================================================
  110.         ' If in MouseMode then
  111.         '   if button is pressed, check where mouse is and react acccordingly.
  112.         '   if button not pressed, switch to keyboard mode.
  113.         '===================================================================
  114.         IF mouseMode THEN
  115.             MousePoll mouseRow, mouseCol, lButton, rButton
  116.             IF lButton THEN
  117.                 IF mouseRow = 1 THEN
  118.                     GOSUB MenuDoGetMouseMenu
  119.                 ELSE
  120.                     GOSUB MenuDoGetMouseItem
  121.                 END IF
  122.             ELSE
  123.                 mouseMode = FALSE
  124.                 GOSUB MenuDoMouseRelease
  125.                 IF NOT pulldown THEN
  126.                     GOSUB MenuDoShowTitleAccessKeys
  127.                 END IF
  128.             END IF
  129.         ELSE
  130.  
  131.             '===============================================================
  132.             ' If in keyboard mode, show the cursor, wait for key, hide cursor
  133.             ' Perform the desired action based on what key was pressed.
  134.             '===============================================================
  135.  
  136.             GOSUB MenuDoShowCursor
  137.             GOSUB MenuDoGetKey
  138.             GOSUB MenuDoHideCursor
  139.  
  140.             SELECT CASE kbd$
  141.                 CASE "enter":       GOSUB MenuDoEnter
  142.                 CASE "up":          GOSUB MenuDoUp
  143.                 CASE "down":        GOSUB menuDoDown
  144.                 CASE "left":        GOSUB MenuDoLeft
  145.                 CASE "right":       GOSUB MenuDoRight
  146.                 CASE "escape":      GOSUB MenuDoEscape
  147.                 CASE "altReleased": GOSUB MenuDoAltReleased
  148.                 CASE "mouse":       GOSUB MenuDoMousePress
  149.                 CASE ELSE:          GOSUB MenuDoAccessKey
  150.             END SELECT
  151.         END IF
  152.     WEND
  153.     GOSUB MenuDoHideTitleAccessKeys
  154.     EXIT SUB
  155.  
  156. '===========================================================================
  157. ' Initialize variables for proper MenuDo execution.
  158. '===========================================================================
  159.  
  160. MenuDoInit:
  161.     REDIM buffer$(MAXMENU), copyFlag(MAXMENU)             'Stores screen backround
  162.  
  163.     FOR a = 1 TO MAXMENU
  164.         buffer$(a) = ""                         '1 buffer per menu
  165.         copyFlag(a) = FALSE                     'FALSE means not copied yet
  166.     NEXT a
  167.  
  168.     pulldown = FALSE                            'FALSE means no menu is shown
  169.     MenuDoDone = FALSE                          'FALSE means keep going in loop
  170.  
  171.     altWasReleased = FALSE                      'Set to TRUE if ALT is pressed
  172.                                                 'and then released
  173.  
  174.     altWasPressedAgain = FALSE                  'Set to TRUE is ALT is pressed
  175.                                                 'and then released, and then
  176.                                                 'pressed again.
  177.  
  178.     '=======================================================================
  179.     ' If mouse installed and button is pressed, then set MouseMode to TRUE
  180.     ' Else, set MouseMode to FALSE
  181.     '=======================================================================
  182.   
  183.     MousePoll mouseRow, mouseCol, lButton, rButton
  184.     IF lButton THEN
  185.         mouseMode = TRUE
  186.         currMenu = 0
  187.         currItem = 0
  188.     ELSE
  189.         mouseMode = FALSE
  190.         currMenu = 1
  191.         currItem = 0
  192.         GOSUB MenuDoShowTitleAccessKeys
  193.     END IF
  194.  
  195. RETURN
  196.  
  197. '===========================================================================
  198. ' This shows the cursor at the location CurrMenu,CurrItem.
  199. '===========================================================================
  200.  
  201. MenuDoShowCursor:
  202.  
  203.     MouseHide
  204.     IF currMenu <> 0 AND RTRIM$(GloItem(currMenu, currItem).text) <> "-" THEN
  205.         IF currItem = 0 THEN
  206.             COLOR GloMenu.cursorFore, GloMenu.cursorBack
  207.             LOCATE 1, GloTitle(currMenu).lColTitle
  208.             PRINT " "; RTRIM$(GloTitle(currMenu).text); " ";
  209.             IF NOT mouseMode THEN
  210.                COLOR GloMenu.cursorHi, GloMenu.cursorBack
  211.                LOCATE 1, GloTitle(currMenu).lColTitle + GloTitle(currMenu).accessKey
  212.                PRINT MID$(GloTitle(currMenu).text, GloTitle(currMenu).accessKey, 1);
  213.             END IF
  214.         ELSE
  215.             IF GloItem(currMenu, currItem).state = 2 THEN
  216.                 chk$ = CHR$(175)
  217.             ELSE
  218.                 chk$ = " "
  219.             END IF
  220.  
  221.             COLOR GloMenu.cursorFore, GloMenu.cursorBack
  222.             LOCATE GloItem(currMenu, currItem).row, GloTitle(currMenu).lColItem + 1
  223.             PRINT chk$; LEFT$(GloItem(currMenu, currItem).text, GloTitle(currMenu).itemLength); " ";
  224.  
  225.             IF GloItem(currMenu, currItem).state > 0 THEN
  226.                 COLOR GloMenu.cursorHi, GloMenu.cursorBack
  227.                 LOCATE GloItem(currMenu, currItem).row, col + GloItem(currMenu, currItem).accessKey + 1
  228.                 PRINT MID$(GloItem(currMenu, currItem).text, GloItem(currMenu, currItem).accessKey, 1);
  229.             END IF
  230.  
  231.         END IF
  232.     END IF
  233.     MouseShow
  234.  
  235. RETURN
  236.  
  237. '===========================================================================
  238. ' This hides the cursor at the location CurrMenu,CurrItem.
  239. '===========================================================================
  240.  
  241. MenuDoHideCursor:
  242.  
  243.     MouseHide
  244.     IF currMenu <> 0 AND RTRIM$(GloItem(currMenu, currItem).text) <> "-" THEN
  245.         IF currItem = 0 THEN
  246.             SELECT CASE GloTitle(currMenu).state
  247.                 CASE 0: COLOR GloMenu.disabled, GloMenu.back
  248.                 CASE 1, 2: COLOR GloMenu.fore, GloMenu.back
  249.                 CASE ELSE
  250.             END SELECT
  251.             LOCATE 1, GloTitle(currMenu).lColTitle
  252.             PRINT " "; RTRIM$(GloTitle(currMenu).text); " ";
  253.  
  254.             IF GloTitle(currMenu).state > 0 THEN
  255.                 COLOR GloMenu.highlight, GloMenu.back
  256.                 LOCATE 1, GloTitle(currMenu).lColTitle + GloTitle(currMenu).accessKey
  257.                 PRINT MID$(GloTitle(currMenu).text, GloTitle(currMenu).accessKey, 1);
  258.             END IF
  259.         ELSE
  260.             IF GloItem(currMenu, currItem).state = 2 THEN
  261.                 chk$ = CHR$(175)
  262.             ELSE
  263.                 chk$ = " "
  264.             END IF
  265.             SELECT CASE GloItem(currMenu, currItem).state
  266.                 CASE 0: COLOR GloMenu.disabled, GloMenu.back
  267.                 CASE 1, 2: COLOR GloMenu.fore, GloMenu.back
  268.                 CASE ELSE
  269.             END SELECT
  270.             LOCATE GloItem(currMenu, currItem).row, GloTitle(currMenu).lColItem + 1
  271.             PRINT chk$; LEFT$(GloItem(currMenu, currItem).text, GloTitle(currMenu).itemLength); " ";
  272.  
  273.             IF GloItem(currMenu, currItem).state > 0 THEN
  274.                 COLOR GloMenu.highlight, GloMenu.back
  275.                 LOCATE GloItem(currMenu, currItem).row, col + GloItem(currMenu, currItem).accessKey + 1
  276.                 PRINT MID$(GloItem(currMenu, currItem).text, GloItem(currMenu, currItem).accessKey, 1);
  277.             END IF
  278.  
  279.         END IF
  280.     END IF
  281.     MouseShow
  282. RETURN
  283.  
  284. '===========================================================================
  285. ' Handles state where mouse is at row #1.
  286. '===========================================================================
  287.  
  288. MenuDoGetMouseMenu:
  289.  
  290.     '=======================================================================
  291.     ' Computes the menu number based on mouse column location.  Uses info
  292.     ' calculated in MenuShow()
  293.     '=======================================================================
  294.  
  295.     newMenu = CVI(MID$(GloMenu.menuIndex, mouseCol * 2 - 1, 2))
  296.  
  297.     IF GloTitle(newMenu).state <> 1 THEN
  298.         newMenu = 0
  299.     END IF
  300.  
  301.     '=======================================================================
  302.     ' If new menu<>current menu, hide current menu, show new menu, assign new
  303.     ' menu to current menu
  304.     '=======================================================================
  305.  
  306.     IF newMenu <> currMenu THEN
  307.         GOSUB MenuDoHidePullDown
  308.         currMenu = newMenu
  309.         currItem = 0
  310.         GOSUB menuDoShowPullDown
  311.     END IF
  312.  
  313. RETURN
  314.  
  315. '===========================================================================
  316. ' Handles state where mouse is not in row #1.  If a menu is down, it picks
  317. ' the proper menu item based on which row the mouse is located
  318. '===========================================================================
  319.  
  320. MenuDoGetMouseItem:
  321.  
  322.     '=======================================================================
  323.     ' If pulldown, and mouse column is within the menu area, then compute new
  324.     ' item  based on computations done in MenuShow.  If not in box, then new
  325.     ' item = 0
  326.     '=======================================================================
  327.  
  328.     IF pulldown THEN
  329.         IF mouseCol >= GloTitle(currMenu).lColItem AND mouseCol <= GloTitle(currMenu).rColItem AND mouseRow <= GloTitle(currMenu).lowestRow AND mouseRow - 2 <= MAXITEM THEN
  330.             newItem = GloItem(currMenu, mouseRow - 2).index
  331.         ELSE
  332.             newItem = 0
  333.         END IF
  334.  
  335.         ' ===================================================================
  336.         ' If current item <> new item, hide old cursor, show new cursor,
  337.         ' assign new item to current item.
  338.         ' ===================================================================
  339.  
  340.         IF currItem <> newItem THEN
  341.             IF currItem <> 0 THEN
  342.                 GOSUB MenuDoHideCursor
  343.             END IF
  344.             currItem = newItem
  345.             GOSUB MenuDoShowCursor
  346.         END IF
  347.     END IF
  348. RETURN
  349.  
  350. ' ===========================================================================
  351. ' Handles state when MenuDo is in mouse mode, and mouse button is released.
  352. ' ===========================================================================
  353.  
  354. MenuDoMouseRelease:
  355.     menuMode = FALSE
  356.  
  357.     ' =======================================================================
  358.     ' If no menu selected, then exit MenuDo returning 0s for menu and item
  359.     ' =======================================================================
  360.  
  361.     IF currMenu = 0 THEN
  362.         GloMenu.currMenu = 0
  363.         GloMenu.currItem = 0
  364.         MenuDoDone = TRUE
  365.     ELSE
  366.  
  367.         ' ===================================================================
  368.         ' If menu is down, but no item is selected then
  369.         '    if mouse is on the top row, simply gosub the MenuDoDown routine
  370.         '    else hide menu then exit MenuDo returning 0's for menu and item
  371.         ' ===================================================================
  372.  
  373.         IF currItem = 0 THEN
  374.             IF mouseRow = 1 THEN
  375.                 GOSUB menuDoDown
  376.             ELSE
  377.                 GOSUB MenuDoHidePullDown
  378.                 GloMenu.currMenu = 0
  379.                 GloMenu.currItem = 0
  380.                 MenuDoDone = TRUE
  381.             END IF
  382.         ELSE
  383.  
  384.             ' ===============================================================
  385.             ' If current (menu,item)'s state is disabled, then just beep
  386.             ' ===============================================================
  387.  
  388.             IF GloItem(currMenu, currItem).state = 0 THEN
  389.                 BEEP
  390.  
  391.             ' ===============================================================
  392.             ' If current (menu,item)'s state is a line
  393.             ' then exit MenuDo returning 0s for menu and item
  394.             ' ===============================================================
  395.  
  396.             ELSEIF RTRIM$(GloItem(currMenu, currItem).text) = "-" THEN
  397.                 GOSUB MenuDoHidePullDown
  398.                 GloMenu.currMenu = 0
  399.                 GloMenu.currItem = 0
  400.                 MenuDoDone = TRUE
  401.             ELSE
  402.  
  403.                 ' ===========================================================
  404.                 ' Otherwise, selection must be valid, exit MenuDo, returning
  405.                 ' proper menu,item pair in the proper global variables
  406.                 ' ===========================================================
  407.                 GOSUB MenuDoHidePullDown
  408.                 GloMenu.currMenu = currMenu
  409.                 GloMenu.currItem = currItem
  410.                 MenuDoDone = TRUE
  411.             END IF
  412.         END IF
  413.     END IF
  414. RETURN
  415.  
  416. ' ==========================================================================
  417. ' This routine shows the menu bar's access keys
  418. ' ==========================================================================
  419.  
  420. MenuDoShowTitleAccessKeys:
  421.     MouseHide
  422.     COLOR GloMenu.highlight, GloMenu.back
  423.     FOR menu = 1 TO MAXMENU
  424.         IF GloTitle(menu).state = 1 THEN
  425.             LOCATE 1, GloTitle(menu).lColTitle + GloTitle(menu).accessKey
  426.             PRINT MID$(GloTitle(menu).text, GloTitle(menu).accessKey, 1);
  427.         END IF
  428.     NEXT menu
  429.     MouseShow
  430. RETURN
  431.  
  432.  
  433. ' ===========================================================================
  434. ' This routine hides the menu bar's access keys
  435. ' ===========================================================================
  436.  
  437. MenuDoHideTitleAccessKeys:
  438.     MouseHide
  439.     COLOR GloMenu.fore, GloMenu.back
  440.     FOR menu = 1 TO MAXMENU
  441.         IF GloTitle(menu).state = 1 THEN
  442.             LOCATE 1, GloTitle(menu).lColTitle + GloTitle(menu).accessKey
  443.             PRINT MID$(GloTitle(menu).text, GloTitle(menu).accessKey, 1);
  444.         END IF
  445.     NEXT menu
  446.     MouseShow
  447. RETURN
  448.  
  449. ' ===========================================================================
  450. ' Waits for key press, then returns the key press.  It also returns several
  451. ' tokens such as "menu", or "altReleased" in special cases.  Read on...
  452. ' ===========================================================================
  453.  
  454. MenuDoGetKey:
  455.     DO
  456.         kbd$ = INKEY$
  457.  
  458.         ' ===================================================================
  459.         ' If ALT key pressed, then if it was a access key (Alt+A..) reduce
  460.         '  the Alt+A to A.
  461.         '  Also set the altPressed flags to reflect the current state of the
  462.         '  ALT key.
  463.         ' ===================================================================
  464.  
  465.         IF GetShiftState(3) THEN
  466.             IF kbd$ = "" THEN
  467.                 IF altWasReleased THEN
  468.                     altWasPressedAgain = TRUE
  469.                 END IF
  470.             ELSE
  471.                 altWasPressedAgain = FALSE
  472.                 kbd$ = AltToASCII(kbd$)
  473.             END IF
  474.             altWasReleased = FALSE
  475.         ELSE
  476.  
  477.             ' ===============================================================
  478.             ' If ALT key is released (initially), then pressed, then released
  479.             ' again with no other action in between, then return the
  480.             ' token "altReleased"
  481.             ' ===============================================================
  482.  
  483.             IF altWasPressedAgain THEN
  484.                 kbd$ = "altReleased"
  485.                 altWasPressedAgain = FALSE
  486.             ELSE
  487.  
  488.                 ' ===========================================================
  489.                 ' Based on the key that was pressed, return the proper token
  490.                 ' ===========================================================
  491.  
  492.                 altWasReleased = TRUE
  493.                                            
  494.                 SELECT CASE kbd$
  495.                     CASE CHR$(27) + "": kbd$ = "escape"
  496.                     CASE CHR$(32) + "": kbd$ = ""
  497.                     CASE CHR$(13) + "": kbd$ = "enter"
  498.                     CASE CHR$(0) + "H": kbd$ = "up"
  499.                     CASE CHR$(0) + "P": kbd$ = "down"
  500.                     CASE CHR$(0) + "K": kbd$ = "left"
  501.                     CASE CHR$(0) + "M": kbd$ = "right"
  502.                     CASE ELSE
  503.                         IF LEN(kbd$) = 1 THEN
  504.                             kbd$ = UCASE$(kbd$)
  505.                         END IF
  506.                 END SELECT
  507.             END IF
  508.         END IF
  509.  
  510.         ' ===================================================================
  511.         ' If mouse button is pressed, it overrides all key actions, and
  512.         ' the token "mouse" is returned
  513.         ' ===================================================================
  514.  
  515.         MousePoll mouseRow, mouseCol, lButton, rButton
  516.         IF lButton THEN
  517.             kbd$ = "mouse"
  518.         END IF
  519.  
  520.     LOOP UNTIL kbd$ <> ""
  521.     
  522. RETURN
  523.  
  524.  
  525. ' ===========================================================================
  526. ' Handles the state where the up arrow is pressed.  It searches for the
  527. ' first non empty, non "-" (dashed) item.
  528. ' ===========================================================================
  529.  
  530. MenuDoUp:
  531.     IF currItem <> 0 THEN
  532.         DO
  533.             currItem = (currItem + MAXITEM - 2) MOD MAXITEM + 1
  534.         LOOP UNTIL GloItem(currMenu, currItem).state >= 0 AND RTRIM$(GloItem(currMenu, currItem).text) <> "-"
  535.     END IF
  536. RETURN
  537.  
  538.  
  539. ' ===========================================================================
  540. ' Handles 2 different states:
  541. '
  542. '  State 1: Menu is open, and the down arrow is pressed.
  543. '
  544. '  State 2: Any time a new menu is opened, and the top item
  545. '      is to be the current item.  Specifically:
  546. '          - When no menu is opened, and the down arrow is pressed
  547. '          - When the mouse is released over the menu title
  548. '          - When a menu is opened, and the user hits right/left arrow
  549. '          - When enter is pressed while cursor is on title bar
  550. '          - When a access key is used on the title bar.
  551. ' ===========================================================================
  552.  
  553. menuDoDown:
  554.     DO
  555.         IF currItem = 0 THEN
  556.             GOSUB MenuDoHideTitleAccessKeys
  557.             GOSUB menuDoShowPullDown
  558.             currItem = (currItem) MOD MAXITEM + 1
  559.         ELSEIF currItem > 0 THEN
  560.             currItem = (currItem) MOD MAXITEM + 1
  561.         END IF
  562.        
  563.     LOOP UNTIL GloItem(currMenu, currItem).state >= 0 AND RTRIM$(GloItem(currMenu, currItem).text) <> "-"
  564. RETURN
  565.  
  566.  
  567. ' ===========================================================================
  568. ' Handles state when the left arrow is pressed.  If a menu is down, it
  569. ' hides it.  It then finds the first valid menu to the left.  If the menu
  570. ' was initially down, then the new menu is pulled down as well
  571. ' ===========================================================================
  572.  
  573. MenuDoLeft:
  574.     IF pulldown THEN
  575.         GOSUB MenuDoHidePullDown
  576.         pulldown = TRUE
  577.     END IF
  578.  
  579.     DO
  580.         currMenu = (currMenu + MAXMENU - 2) MOD MAXMENU + 1
  581.     LOOP UNTIL GloTitle(currMenu).state = 1
  582.     
  583.     IF pulldown THEN
  584.         currItem = 0
  585.         GOSUB menuDoDown
  586.     END IF
  587. RETURN
  588.  
  589.  
  590. ' ===========================================================================
  591. ' Handles state when the right arrow is pressed.  If a menu is down, it
  592. ' hides it.  It then finds the first valid menu to the right.  If the menu
  593. ' was initially down, then the new menu is pulled down as well
  594. ' ===========================================================================
  595.  
  596. MenuDoRight:
  597.     IF pulldown THEN
  598.         GOSUB MenuDoHidePullDown
  599.         pulldown = TRUE
  600.     END IF
  601.  
  602.     DO
  603.         currMenu = (currMenu) MOD MAXMENU + 1
  604.     LOOP UNTIL GloTitle(currMenu).state = 1
  605.  
  606.     IF pulldown THEN
  607.         currItem = 0
  608.         GOSUB menuDoDown
  609.     END IF
  610. RETURN
  611.  
  612.  
  613. ' ===========================================================================
  614. ' Handles state when the ESC key is pressed.  First hides the menu, and
  615. ' then exits menuDo, returning 0's in the proper global variables
  616. ' ===========================================================================
  617.  
  618. MenuDoEscape:
  619.     GOSUB MenuDoHidePullDown
  620.     GloMenu.currMenu = 0
  621.     GloMenu.currItem = 0
  622.     MenuDoDone = TRUE
  623. RETURN
  624.  
  625. ' ===========================================================================
  626. ' Handles state when Enter is pressed.  If on a valid item, return the
  627. ' proper (menu,item) pair and exit.  Else beep.  If on a valid menu
  628. ' this will open the menu by calling MenuDoDown
  629. ' ===========================================================================
  630.  
  631. MenuDoEnter:
  632.     IF currItem = 0 THEN
  633.         IF GloTitle(currMenu).state = 0 THEN
  634.             BEEP
  635.         ELSE
  636.             GOSUB menuDoDown
  637.         END IF
  638.     ELSE
  639.         IF GloItem(currMenu, currItem).state <= 0 THEN
  640.             BEEP
  641.         ELSE
  642.             GOSUB MenuDoHidePullDown
  643.             GloMenu.currMenu = currMenu
  644.             GloMenu.currItem = currItem
  645.             MenuDoDone = TRUE
  646.         END IF
  647.     END IF
  648. RETURN
  649.  
  650.  
  651. ' ===========================================================================
  652. ' If ALT pressed and released with nothing else happening in between, it
  653. ' will exit if no menu is open, or close the menu if one is open.
  654. ' ===========================================================================
  655.  
  656. MenuDoAltReleased:
  657.     IF pulldown THEN
  658.         GOSUB MenuDoHidePullDown
  659.         currItem = 0
  660.         GOSUB MenuDoShowTitleAccessKeys
  661.     ELSE
  662.         GloMenu.currMenu = 0
  663.         GloMenu.currItem = 0
  664.         MenuDoDone = TRUE
  665.     END IF
  666. RETURN
  667.  
  668.  
  669. ' ===========================================================================
  670. ' If mouse is pressed while in keyboard mode, this routine assigns
  671. ' TRUE to MouseMode, resets the item, and hides the access keys
  672. ' ===========================================================================
  673.  
  674. MenuDoMousePress:
  675.     mouseMode = TRUE
  676.     currItem = 0
  677.     IF NOT pulldown THEN
  678.         GOSUB MenuDoHideTitleAccessKeys
  679.     END IF
  680. RETURN
  681.  
  682.  
  683. ' ===========================================================================
  684. ' If a access key is pressed
  685. ' ===========================================================================
  686.  
  687. MenuDoAccessKey:
  688.  
  689.     ' =======================================================================
  690.     ' If an access key is pressed
  691.     '   If no menu selected, search titles for matching access key, and open
  692.     '      than menu.
  693.     ' =======================================================================
  694.  
  695.     IF currItem = 0 THEN
  696.         newMenu = (currMenu + MAXMENU - 2) MOD MAXMENU + 1
  697.         loopEnd = (currMenu + MAXMENU - 2) MOD MAXMENU + 1
  698.         DO
  699.             newMenu = (newMenu) MOD MAXMENU + 1
  700.         LOOP UNTIL (UCASE$(MID$(GloTitle(newMenu).text, GloTitle(newMenu).accessKey, 1)) = kbd$ AND GloTitle(newMenu).state = 1) OR newMenu = loopEnd
  701.  
  702.         IF kbd$ = UCASE$(MID$(GloTitle(newMenu).text, GloTitle(newMenu).accessKey, 1)) THEN
  703.             currMenu = newMenu
  704.             GOSUB menuDoDown
  705.         END IF
  706.     ELSE
  707.  
  708.         ' ===================================================================
  709.         ' If menu is selected, search items for matching access key, and
  710.         ' select that (menu,item) and exit MenuDo if item is enabled
  711.         ' ===================================================================
  712.  
  713.         newItem = (currItem + MAXITEM - 2) MOD MAXITEM + 1
  714.         loopEnd = (currItem + MAXITEM - 2) MOD MAXITEM + 1
  715.         DO
  716.             newItem = (newItem) MOD MAXITEM + 1
  717.         LOOP UNTIL (UCASE$(MID$(GloItem(currMenu, newItem).text, GloItem(currMenu, newItem).accessKey, 1)) = kbd$ AND GloItem(currMenu, newItem).state > 0 AND RTRIM$(GloItem(currMenu, newItem).text) <> "-") OR newItem = loopEnd
  718.  
  719.                                         
  720.         IF kbd$ = UCASE$(MID$(GloItem(currMenu, newItem).text, GloItem(currMenu, newItem).accessKey, 1)) THEN
  721.             currItem = newItem
  722.            
  723.             IF GloItem(currMenu, currItem).state <= 0 THEN
  724.                 BEEP
  725.             ELSE
  726.                 GOSUB MenuDoHidePullDown
  727.                 GloMenu.currMenu = currMenu
  728.                 GloMenu.currItem = currItem
  729.                 MenuDoDone = TRUE
  730.             END IF
  731.         END IF
  732.     END IF
  733. RETURN
  734.  
  735. ' ===========================================================================
  736. ' Draws the menu -- only if menu is enabled.
  737. ' ===========================================================================
  738.  
  739. menuDoShowPullDown:
  740.     IF currMenu <> 0 AND GloTitle(currMenu).state = 1 THEN
  741.  
  742.         ' ===================================================================
  743.         ' Copies the background if this is the first time this particular
  744.         ' menu is being drawn
  745.         ' ===================================================================
  746.  
  747.         MouseHide
  748.         IF NOT copyFlag(currMenu) THEN
  749.             IF GloTitle(currMenu).rColItem - GloTitle(currMenu).lColItem < LEN(GloTitle(currMenu).text) THEN
  750.                 GloTitle(currMenu).rColItem = GloTitle(currMenu).lColItem + LEN(GloTitle(currMenu).text)
  751.             END IF
  752.  
  753.             GetBackground 1, GloTitle(currMenu).lColItem, GloTitle(currMenu).lowestRow, GloTitle(currMenu).rColItem + 2, buffer$(currMenu)
  754.             copyFlag(currMenu) = TRUE
  755.         END IF
  756.  
  757.         ' ===================================================================
  758.         ' Draw the menu, this is pretty straight forward
  759.         ' ===================================================================
  760.         pulldown = TRUE
  761.         length = GloTitle(currMenu).itemLength
  762.         IF length = 0 THEN length = 6
  763.         lowestRow = 3
  764.         col = GloTitle(currMenu).lColItem
  765.  
  766.         COLOR GloMenu.cursorFore, GloMenu.cursorBack
  767.         LOCATE 1, GloTitle(currMenu).lColTitle
  768.         PRINT " "; RTRIM$(GloTitle(currMenu).text); " ";
  769.  
  770.         COLOR GloMenu.fore, GloMenu.back
  771.         LOCATE 2, col
  772.         PRINT "┌"; STRING$(length + 2, "─"); "┐"
  773.  
  774.         FOR item = 1 TO MAXITEM
  775.             IF GloItem(currMenu, item).state >= 0 THEN
  776.                 IF GloItem(currMenu, item).state = 2 THEN
  777.                     chk$ = CHR$(175)
  778.                 ELSE
  779.                     chk$ = " "
  780.                 END IF
  781.  
  782.                 LOCATE GloItem(currMenu, item).row, col
  783.                 COLOR GloMenu.fore, GloMenu.back
  784.  
  785.                 IF RTRIM$(GloItem(currMenu, item).text) = "-" THEN
  786.                     PRINT "├"; STRING$(length + 2, "─"); "┤"
  787.                 ELSE
  788.                     PRINT "│"; chk$;
  789.                     IF GloItem(currMenu, item).state > 0 THEN
  790.                         COLOR GloMenu.fore, GloMenu.back
  791.                     ELSE
  792.                         COLOR GloMenu.disabled, GloMenu.back
  793.                     END IF
  794.                     PRINT LEFT$(GloItem(currMenu, item).text + SPACE$(20), length);
  795.                     COLOR GloMenu.fore, GloMenu.back
  796.                     PRINT " │";
  797.  
  798.                     IF GloItem(currMenu, item).state > 0 THEN
  799.                         COLOR GloMenu.highlight, GloMenu.back
  800.                         LOCATE GloItem(currMenu, item).row, col + GloItem(currMenu, item).accessKey + 1
  801.                         PRINT MID$(GloItem(currMenu, item).text, GloItem(currMenu, item).accessKey, 1);
  802.                     END IF
  803.                 END IF
  804.                 lowestRow = GloItem(currMenu, item).row + 1
  805.             END IF
  806.         NEXT item
  807.  
  808.         COLOR GloMenu.fore, GloMenu.back
  809.         LOCATE lowestRow, col
  810.         PRINT "└"; STRING$(length + 2, "─"); "┘";
  811.  
  812.         rCol = col + length + 5
  813.  
  814.         AttrBox 3, rCol - 1, lowestRow, rCol, 8
  815.         AttrBox lowestRow + 1, col + 2, lowestRow + 1, rCol, 8
  816.     END IF
  817.  
  818.     MouseShow
  819.  
  820. RETURN
  821.  
  822. ' ===========================================================================
  823. ' Replace the background over the menu
  824. ' ===========================================================================
  825.  
  826. MenuDoHidePullDown:
  827.     IF pulldown THEN
  828.         MouseHide
  829.  
  830.         PutBackground 1, GloTitle(currMenu).lColItem, buffer$(currMenu)
  831.         
  832.         MouseShow
  833.         pulldown = FALSE
  834.     END IF
  835. RETURN
  836.    
  837. END SUB
  838.  
  839. SUB MenuEvent
  840.  
  841.     ' =======================================================================
  842.     ' If ALT key is pressed, let MenuDo take over.  NOTE:  This will
  843.     ' not call MenuDo if the ALT key has not been released at least
  844.     ' once since the last time MenuDo was called.  This prevents the menu
  845.     ' from flashing if the user simply holds down the ALT key.
  846.     ' =======================================================================
  847.  
  848.     IF GetShiftState(3) THEN
  849.         IF GloMenu.altKeyReset THEN
  850.             MenuDo
  851.             GloMenu.altKeyReset = FALSE
  852.         END IF
  853.     ELSE
  854.         GloMenu.altKeyReset = TRUE
  855.     END IF
  856.  
  857.     ' =======================================================================
  858.     ' Call MenuDo if the mouse button is down, and the cursor is on the top row
  859.     ' =======================================================================
  860.  
  861.     MousePoll mouseRow, mouseCol, lButton, rButton
  862.     IF mouseRow = 1 AND lButton THEN
  863.         MenuDo
  864.     END IF
  865.  
  866. END SUB
  867.  
  868. SUB MenuInit
  869.  
  870.     ' =======================================================================
  871.     '  Initialize global menu arrays
  872.     ' =======================================================================
  873.  
  874.     FOR menu = 1 TO MAXMENU
  875.         GloTitle(menu).text = ""
  876.         GloTitle(menu).state = -1            'state of -1 means "empty"
  877.         GloTitle(menu).rColItem = 0           'These get set in MenuShow
  878.         GloTitle(menu).lColItem = 0           ' |
  879.         GloTitle(menu).rColTitle = 0          ' |
  880.         GloTitle(menu).lColTitle = 0          ' |
  881.         GloTitle(menu).itemLength = 0         ' |
  882.         GloTitle(menu).accessKey = 1            'Initial AccessKey of 1
  883.  
  884.         FOR item = 1 TO MAXITEM
  885.             GloItem(menu, item).text = ""
  886.             GloItem(menu, item).state = -1      'state of -1 means "empty"
  887.             GloItem(menu, item).index = 0       'These get set in MenuShow
  888.             GloItem(menu, item).row = 0         '  |
  889.             GloItem(menu, item).accessKey = 1   'Initial AccessKey of 1
  890.         NEXT item
  891.     NEXT menu
  892.  
  893.     ' =======================================================================
  894.     ' Initialize mouse
  895.     ' =======================================================================
  896.  
  897.     MouseInit
  898.  
  899.     ' =======================================================================
  900.     ' Set initial state of ALT key to "reset"
  901.     ' Clear out shortcut key index
  902.     ' Set initial state of menu to ON
  903.     ' =======================================================================
  904.  
  905.     GloMenu.altKeyReset = TRUE
  906.     GloMenu.shortcutKeyIndex = STRING$(100, 0)
  907.     GloMenu.MenuOn = TRUE
  908.  
  909.     GloMenu.fore = 0
  910.     GloMenu.back = 7
  911.     GloMenu.highlight = 15
  912.     GloMenu.disabled = 8
  913.     GloMenu.cursorFore = 7
  914.     GloMenu.cursorBack = 0
  915.     GloMenu.cursorHi = 15
  916.  
  917. END SUB
  918.  
  919. FUNCTION MenuInkey$ STATIC
  920.  
  921.     ' =======================================================================
  922.     ' Scan keyboard, return KBD$ by default -- unless it is over written below
  923.     ' =======================================================================
  924.  
  925.     kbd$ = INKEY$
  926.     MenuInkey$ = kbd$
  927.  
  928.     ' =======================================================================
  929.     ' Check if KBD$ matches a shortcut key.  If it does, return "menu" instead
  930.     ' of the key that was pressed
  931.     ' =======================================================================
  932.  
  933.     ShortCutKeyEvent kbd$
  934.     IF MenuCheck(2) THEN
  935.         MenuInkey$ = "menu"
  936.     ELSE
  937.  
  938.         ' ===================================================================
  939.         ' Call menu event, which looks at mouse, and state of ALT key
  940.         ' If a menu item is selected, return "menu" instead of KBD$
  941.         ' ===================================================================
  942.  
  943.         MenuEvent
  944.         IF MenuCheck(2) THEN
  945.             MenuInkey$ = "menu"
  946.         END IF
  947.     END IF
  948.  
  949. END FUNCTION
  950.  
  951. SUB MenuItemToggle (menu, item)
  952.  
  953.     IF item >= 0 AND menu >= 1 AND item <= MAXITEM AND menu <= MAXMENU THEN
  954.  
  955.         IF item = 0 OR GloItem(menu, item).state < 1 OR GloItem(menu, item).state > 2 THEN
  956.             SOUND 2000, 40
  957.         ELSE
  958.             GloItem(menu, item).state = 3 - GloItem(menu, item).state
  959.         END IF
  960.  
  961.     END IF
  962. END SUB
  963.  
  964. DEFSNG A-Z
  965. SUB MenuOff
  966.  
  967.     ' =======================================================================
  968.     ' Simply assigns FALSE to the proper global variable
  969.     ' =======================================================================
  970.  
  971.     GloMenu.MenuOn = FALSE
  972.  
  973. END SUB
  974.  
  975. DEFINT A-Z
  976. SUB MenuOn
  977.  
  978.     ' =======================================================================
  979.     ' Simply assigns TRUE to the proper global variable
  980.     ' =======================================================================
  981.  
  982.     GloMenu.MenuOn = TRUE
  983.  
  984. END SUB
  985.  
  986. SUB MenuPreProcess STATIC
  987.  
  988.     currCol = 2     'Represents the col where first menu title is located
  989.    
  990.     ' =======================================================================
  991.     ' Menu index is a fast way of decoding which menu the mouse cursor
  992.     ' is pointing to based on the col of the cursor.  See MENU.BI for details.
  993.     ' =======================================================================
  994.  
  995.     GloMenu.menuIndex = STRING$(160, 0)
  996.  
  997.     ' =======================================================================
  998.     ' Process each menu, one at a time
  999.     ' =======================================================================
  1000.  
  1001.     FOR menu = 1 TO MAXMENU
  1002.  
  1003.         ' ===================================================================
  1004.         ' If state is empty, or text is "" then clear out data for that menu
  1005.         ' ===================================================================
  1006.  
  1007.         IF GloTitle(menu).state < 0 OR LEN(RTRIM$(GloTitle(menu).text)) = 0 THEN
  1008.             GloTitle(menu).rColItem = 0
  1009.             GloTitle(menu).lColItem = 0
  1010.             GloTitle(menu).rColTitle = 0
  1011.             GloTitle(menu).lColTitle = 0
  1012.             GloTitle(menu).itemLength = 0
  1013.             GloTitle(menu).state = -1
  1014.        ELSE
  1015.             ' ===============================================================
  1016.             ' else, assign data about the column location to the global storage
  1017.             ' ===============================================================
  1018.  
  1019.             GloTitle(menu).lColTitle = currCol
  1020.             GloTitle(menu).rColTitle = currCol + LEN(RTRIM$(GloTitle(menu).text)) + 1
  1021.             GloTitle(menu).lColItem = currCol - 1
  1022.  
  1023.             IF GloTitle(menu).rColTitle > MAXCOL THEN
  1024.                 BEEP: CLS : PRINT "Menu bar longer than screen!  Cannot function!"
  1025.                 END
  1026.             END IF
  1027.  
  1028.             ' ===============================================================
  1029.             ' Update the index about where the menu is located, increment
  1030.             ' currCol
  1031.             ' ===============================================================
  1032.  
  1033.             FOR index = currCol TO currCol + LEN(RTRIM$(GloTitle(menu).text)) + 1
  1034.                 MID$(GloMenu.menuIndex, index * 2 - 1, 2) = MKI$(menu)
  1035.             NEXT index
  1036.             
  1037.             currCol = currCol + LEN(RTRIM$(GloTitle(menu).text)) + 2
  1038.  
  1039.             ' ===============================================================
  1040.             ' Process the items in the menu, computing the
  1041.             ' longest item, and preparing the row index
  1042.             ' ===============================================================
  1043.  
  1044.             GloTitle(menu).itemLength = 0
  1045.             currRow = 3
  1046.             iFlag = FALSE
  1047.  
  1048.             FOR item = 1 TO MAXITEM
  1049.                 GloItem(menu, currRow - 2).index = 0
  1050.                 IF GloItem(menu, item).state >= 0 THEN
  1051.                     GloItem(menu, currRow - 2).index = item
  1052.                     GloItem(menu, item).row = currRow
  1053.                     currRow = currRow + 1
  1054.                     IF LEN(RTRIM$(GloItem(menu, item).text)) > GloTitle(menu).itemLength THEN
  1055.                         GloTitle(menu).itemLength = LEN(RTRIM$(GloItem(menu, item).text))
  1056.                     END IF
  1057.                     iFlag = TRUE
  1058.                 END IF
  1059.             NEXT item
  1060.  
  1061.             ' ===============================================================
  1062.             ' If all items were empty, disable the menu itself
  1063.             ' else, assign the longest length to the proper variable
  1064.             ' ===============================================================
  1065.  
  1066.             IF NOT iFlag THEN
  1067.                 GloTitle(menu).state = 0
  1068.             ELSE
  1069.                 GloTitle(menu).rColItem = GloTitle(menu).lColItem + GloTitle(menu).itemLength + 3
  1070.                 IF GloTitle(menu).rColItem > MAXCOL - 2 THEN
  1071.                    diff = GloTitle(menu).rColItem - (MAXCOL - 2)
  1072.                    GloTitle(menu).rColItem = GloTitle(menu).rColItem - diff
  1073.                    GloTitle(menu).lColItem = GloTitle(menu).lColItem - diff
  1074.                 END IF
  1075.             END IF
  1076.  
  1077.         END IF
  1078.  
  1079.         GloTitle(menu).lowestRow = currRow + 1
  1080.     NEXT menu
  1081.  
  1082. END SUB
  1083.  
  1084. SUB MenuSet (menu, item, state, text$, accessKey) STATIC
  1085.  
  1086.     IF accessKey > LEN(text$) THEN accessKey = LEN(text$)
  1087.  
  1088.     IF item >= 0 AND menu >= 1 AND item <= MAXITEM AND menu <= MAXMENU THEN
  1089.  
  1090.         ' ===================================================================
  1091.         ' Assign parameters to proper global menu variables
  1092.         ' ===================================================================
  1093.  
  1094.         IF item = 0 THEN
  1095.             IF state < -1 OR state > 1 THEN
  1096.                 SOUND 3000, 40
  1097.             ELSE
  1098.                 GloTitle(menu).text = text$
  1099.                 GloTitle(menu).state = state
  1100.                 GloTitle(menu).accessKey = accessKey
  1101.             END IF
  1102.         ELSE
  1103.             IF state < -1 OR state > 2 THEN
  1104.                 SOUND 4000, 40
  1105.             ELSE
  1106.                 GloItem(menu, item).text = text$
  1107.                 GloItem(menu, item).state = state
  1108.                 GloItem(menu, item).accessKey = accessKey
  1109.             END IF
  1110.         END IF
  1111.     END IF
  1112.  
  1113. END SUB
  1114.  
  1115. SUB MenuSetState (menu, item, state) STATIC
  1116.  
  1117.     ' =======================================================================
  1118.     ' Assign parameters to proper global menu variables
  1119.     ' =======================================================================
  1120.  
  1121.     IF item = 0 THEN
  1122.         IF state < 0 OR state > 1 OR GloTitle(menu).state < 0 THEN
  1123.             SOUND 5000, 40
  1124.         ELSE
  1125.             GloTitle(menu).state = state
  1126.         END IF
  1127.     ELSE
  1128.         IF state < 0 OR state > 2 OR GloItem(menu, item).state < 0 THEN
  1129.             SOUND 6000, 40
  1130.         ELSE
  1131.             GloItem(menu, item).state = state
  1132.         END IF
  1133.     END IF
  1134.  
  1135. END SUB
  1136.  
  1137. DEFSNG A-Z
  1138. SUB MenuShow
  1139.  
  1140.     ' =======================================================================
  1141.     ' This section actually prints the menu on the screen
  1142.     ' =======================================================================
  1143.  
  1144.     COLOR GloMenu.fore, GloMenu.back
  1145.     LOCATE 1, 1
  1146.     PRINT SPACE$(MAXCOL);
  1147.  
  1148.     FOR menu = 1 TO MAXMENU
  1149.         SELECT CASE GloTitle(menu).state
  1150.             CASE 0:
  1151.                 COLOR GloMenu.disabled, GloMenu.back
  1152.                 LOCATE 1, GloTitle(menu).lColTitle + 1
  1153.                 PRINT RTRIM$(GloTitle(menu).text$);
  1154.             CASE 1:
  1155.                 COLOR GloMenu.fore, GloMenu.back
  1156.                 LOCATE 1, GloTitle(menu).lColTitle + 1
  1157.                 PRINT RTRIM$(GloTitle(menu).text$);
  1158.             CASE ELSE
  1159.         END SELECT
  1160.  
  1161.     NEXT menu
  1162.  
  1163. END SUB
  1164.  
  1165. DEFINT A-Z
  1166. SUB ShortCutKeyDelete (menu, item) STATIC
  1167.  
  1168.     '=======================================================================
  1169.     ' Search through shortcut key index until the menu,item pair is found
  1170.     ' or the end of the list is reached.
  1171.     '=======================================================================
  1172.  
  1173.     ptr = -1
  1174.     DO
  1175.         ptr = ptr + 1
  1176.         temp = CVI(MID$(GloMenu.shortcutKeyIndex, ptr * 4 + 1, 2))
  1177.         testMenu = INT(temp / 256)
  1178.         testItem = INT(temp MOD 256)
  1179.     LOOP UNTIL (menu = testMenu AND item = testItem) OR testMenu = 0 AND testItem = 0 OR ptr = 25
  1180.  
  1181.     '=======================================================================
  1182.     ' If a match is found, delete the shortcut key by squeezing out the four
  1183.     ' bytes that represents the shortcut key, and adding four chr$(0) at the
  1184.     ' end.
  1185.     '=======================================================================
  1186.  
  1187.     IF menu = testMenu AND item = testItem THEN
  1188.         GloMenu.shortcutKeyIndex = LEFT$(GloMenu.shortcutKeyIndex, ptr * 4) + RIGHT$(GloMenu.shortcutKeyIndex, 96 - ptr * 4) + STRING$(4, 0)
  1189.     END IF
  1190.  
  1191. END SUB
  1192.  
  1193. SUB ShortCutKeyEvent (theKey$)
  1194.  
  1195.     '=======================================================================
  1196.     ' If menu event trapping turned off, return immediately
  1197.     '=======================================================================
  1198.  
  1199.     IF NOT GloMenu.MenuOn THEN
  1200.         EXIT SUB
  1201.     END IF
  1202.  
  1203.     '=======================================================================
  1204.     ' Make sure the length of theKey$ is two bytes by adding a chr$(0) if
  1205.     ' necessary.  If the length is > 2, make it null.
  1206.     '=======================================================================
  1207.  
  1208.     SELECT CASE LEN(theKey$)
  1209.         CASE 1
  1210.             theKey$ = theKey$ + CHR$(0)
  1211.         CASE 2
  1212.         CASE ELSE
  1213.             theKey$ = ""
  1214.     END SELECT
  1215.  
  1216.     '=======================================================================
  1217.     ' Search the shortcut key list for a match -- only if theKey$ is valid.
  1218.     '=======================================================================
  1219.  
  1220.     IF theKey$ <> "" THEN
  1221.  
  1222.         ptr = -1
  1223.         DO
  1224.             ptr = ptr + 1
  1225.             testKey$ = MID$(GloMenu.shortcutKeyIndex, ptr * 4 + 3, 2)
  1226.  
  1227.         LOOP UNTIL theKey$ = testKey$ OR testKey$ = STRING$(2, 0) OR ptr = 25
  1228.  
  1229.         '===================================================================
  1230.         ' If match is found, make sure menu choice is valid (state > 0)
  1231.         ' If so, assign the proper global variables.
  1232.         '===================================================================
  1233.  
  1234.     IF theKey$ = testKey$ THEN
  1235.             temp = CVI(MID$(GloMenu.shortcutKeyIndex, ptr * 4 + 1, 2))
  1236.             tempMenu = INT(temp / 256)
  1237.             tempItem = INT(temp MOD 256)
  1238.  
  1239.             IF GloItem(tempMenu, tempItem).state > 0 THEN
  1240.                 GloMenu.currMenu = tempMenu
  1241.                 GloMenu.currItem = tempItem
  1242.             END IF
  1243.         END IF
  1244.     END IF
  1245.  
  1246. END SUB
  1247.  
  1248. SUB ShortCutKeySet (menu, item, shortcutKey$)
  1249.  
  1250.     '=======================================================================
  1251.     ' Make sure the length of theKey$ is two bytes by adding a chr$(0) if
  1252.     ' necessary.  If the length is >2, make it null.
  1253.     '=======================================================================
  1254.  
  1255.     SELECT CASE LEN(shortcutKey$)
  1256.         CASE 1
  1257.             shortcutKey$ = shortcutKey$ + CHR$(0)
  1258.         CASE 2
  1259.         CASE ELSE
  1260.             shortcutKey$ = ""
  1261.     END SELECT
  1262.  
  1263.     '=======================================================================
  1264.     ' First delete the shortcut key, just in case it already exists, and then
  1265.     ' and the shortcut key to the front of the shortcut key index string.
  1266.     '=======================================================================
  1267.  
  1268.     ShortCutKeyDelete menu, item
  1269.     IF shortcutKey$ <> "" THEN
  1270.         newKey$ = MKI$(menu * 256 + item) + shortcutKey$
  1271.         GloMenu.shortcutKeyIndex = newKey$ + LEFT$(GloMenu.shortcutKeyIndex, 396)
  1272.     END IF
  1273.  
  1274. END SUB
  1275.  
  1276.