home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / S12780.ZIP / MENU.BAS < prev    next >
BASIC Source File  |  1990-10-25  |  49KB  |  1,301 lines

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