home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
S12780.ZIP
/
MENU.BAS
< prev
next >
Wrap
BASIC Source File
|
1990-10-25
|
49KB
|
1,301 lines
'============================================================================
'
' MENU.BAS - Pull-down Menu Routines for the User Interface Toolbox in
' Microsoft BASIC 7.1, Professional Development System
' Copyright (C) 1987-1990, Microsoft Corporation
'
' NOTE: This sample source code toolbox is intended to demonstrate some
' of the extended capabilities of Microsoft BASIC 7.1 Professional
' Development system that can help to leverage the professional
' developer's time more effectively. While you are free to use,
' modify, or distribute the routines in this module in any way you
' find useful, it should be noted that these are examples only and
' should not be relied upon as a fully-tested "add-on" library.
'
' PURPOSE: These are the routines which provide support for the pull-down
' menus in the user interface toolbox.
'
' NOTE: These routines have been modified to support under OS/2 both
' full-screen and windowed command prompts using OS/2 API functions
' to provide similar effect to the DOS based code.
'
' All sections of code that have been modified will have a comment
' preseeding the modifications in the following manner :
'
' '| --- Modified to support OS/2 changes ---
' '|
' '| Description of changes
' '| ----------------------
' '|
'
' THIS IS SAMPLE CODE AND IS NOT TO BE CONSIDERED A COMPLETE BUG FREE
' PACKAGE. THIS CODE IS DESIGNED SPECIFICALLY TO RUN UNDER OS/2 PROTECTED
' MODE. THE ORIGINAL CODE HAS NOT BEEN MODIFIED IN ANY WAY, EXCEPT TO
' PROVIDE THIS FUNCTIONALITY.
'
'
'============================================================================
DEFINT A-Z
'$INCLUDE: 'general.bi'
'$INCLUDE: 'mouse.bi'
'$INCLUDE: 'menu.bi'
COMMON SHARED /uitools/ GloMenu AS MenuMiscType
COMMON SHARED /uitools/ GloTitle() AS MenuTitleType
COMMON SHARED /uitools/ GloItem() AS MenuItemType
FUNCTION MenuCheck (action%) STATIC
SELECT CASE action
'=======================================================================
' This simulates "polling" for a menu event. If a menu event occured,
' GloMenu.currMenu and .currItem are set. When MenuCheck(0) is
' called, these values are transfered to .lastMenu and .lastItem.
' MenuCheck(0) then returns the menu number, or 0 (FALSE) if none
' selected as of last call
'=======================================================================
CASE 0
GloMenu.lastMenu = GloMenu.currMenu
GloMenu.lastItem = GloMenu.currItem
GloMenu.currMenu = 0
GloMenu.currItem = 0
MenuCheck = GloMenu.lastMenu
'===================================================================
' Returns the menu item last selected. Functions only after a call
' to MenuCheck(0)
'===================================================================
CASE 1
MenuCheck = GloMenu.lastItem
'===================================================================
' Checks GloMenu.currMenu and .currItem. If both are not 0, this
' returns TRUE meaning a menu has been selected since MenuCheck(0)
' was last called. This does not change any values, it simply
' reports on the current state.
'===================================================================
CASE 2
IF GloMenu.currMenu = 0 OR GloMenu.currItem = 0 THEN
MenuCheck = FALSE
ELSE
MenuCheck = TRUE
END IF
CASE ELSE
MenuCheck = 0
END SELECT
END FUNCTION
SUB MenuColor (fore, back, highlight, disabled, cursorFore, cursorBack, cursorHi)
GloMenu.fore = fore
GloMenu.back = back
GloMenu.highlight = highlight
GloMenu.disabled = disabled
GloMenu.cursorFore = cursorFore
GloMenu.cursorBack = cursorBack
GloMenu.cursorHi = cursorHi
END SUB
SUB MenuDo STATIC
'=======================================================================
' If menu event trapping turned off, return immediately
'=======================================================================
IF NOT GloMenu.MenuOn THEN
EXIT SUB
END IF
'=======================================================================
' Initialize MenuDo's variables, and then enter the main loop
'=======================================================================
GOSUB MenuDoInit
WHILE NOT MenuDoDone
'===================================================================
' If in MouseMode then
' if button is pressed, check where mouse is and react acccordingly.
' if button not pressed, switch to keyboard mode.
'===================================================================
IF mouseMode THEN
MousePoll mouseRow, mouseCol, lButton, rButton
IF lButton THEN
IF mouseRow = 1 THEN
GOSUB MenuDoGetMouseMenu
ELSE
GOSUB MenuDoGetMouseItem
END IF
ELSE
mouseMode = FALSE
GOSUB MenuDoMouseRelease
IF NOT pulldown THEN
GOSUB MenuDoShowTitleAccessKeys
END IF
END IF
ELSE
'===============================================================
' If in keyboard mode, show the cursor, wait for key, hide cursor
' Perform the desired action based on what key was pressed.
'===============================================================
GOSUB MenuDoShowCursor
GOSUB MenuDoGetKey
GOSUB MenuDoHideCursor
SELECT CASE kbd$
CASE "enter": GOSUB MenuDoEnter
CASE "up": GOSUB MenuDoUp
CASE "down": GOSUB menuDoDown
CASE "left": GOSUB MenuDoLeft
CASE "right": GOSUB MenuDoRight
CASE "escape": GOSUB MenuDoEscape
CASE "altReleased": GOSUB MenuDoAltReleased
CASE "mouse": GOSUB MenuDoMousePress
CASE ELSE: GOSUB MenuDoAccessKey
END SELECT
END IF
WEND
GOSUB MenuDoHideTitleAccessKeys
EXIT SUB
'===========================================================================
' Initialize variables for proper MenuDo execution.
'===========================================================================
MenuDoInit:
REDIM buffer$(MAXMENU), copyFlag(MAXMENU) 'Stores screen backround
FOR a = 1 TO MAXMENU
buffer$(a) = "" '1 buffer per menu
copyFlag(a) = FALSE 'FALSE means not copied yet
NEXT a
pulldown = FALSE 'FALSE means no menu is shown
MenuDoDone = FALSE 'FALSE means keep going in loop
altWasReleased = FALSE 'Set to TRUE if ALT is pressed
'and then released
altWasPressedAgain = FALSE 'Set to TRUE is ALT is pressed
'and then released, and then
'pressed again.
'=======================================================================
' If mouse installed and button is pressed, then set MouseMode to TRUE
' Else, set MouseMode to FALSE
'=======================================================================
MousePoll mouseRow, mouseCol, lButton, rButton
IF lButton THEN
mouseMode = TRUE
currMenu = 0
currItem = 0
ELSE
mouseMode = FALSE
currMenu = 1
currItem = 0
GOSUB MenuDoShowTitleAccessKeys
END IF
RETURN
'===========================================================================
' This shows the cursor at the location CurrMenu,CurrItem.
'===========================================================================
MenuDoShowCursor:
MouseHide
IF currMenu <> 0 AND RTRIM$(GloItem(currMenu, currItem).text) <> "-" THEN
IF currItem = 0 THEN
COLOR GloMenu.cursorFore, GloMenu.cursorBack
LOCATE 1, GloTitle(currMenu).lColTitle
PRINT " "; RTRIM$(GloTitle(currMenu).text); " ";
IF NOT mouseMode THEN
COLOR GloMenu.cursorHi, GloMenu.cursorBack
LOCATE 1, GloTitle(currMenu).lColTitle + GloTitle(currMenu).accessKey
PRINT MID$(GloTitle(currMenu).text, GloTitle(currMenu).accessKey, 1);
END IF
ELSE
IF GloItem(currMenu, currItem).state = 2 THEN
chk$ = CHR$(175)
ELSE
chk$ = " "
END IF
COLOR GloMenu.cursorFore, GloMenu.cursorBack
LOCATE GloItem(currMenu, currItem).row, GloTitle(currMenu).lColItem + 1
PRINT chk$; LEFT$(GloItem(currMenu, currItem).text, GloTitle(currMenu).itemLength); " ";
IF GloItem(currMenu, currItem).state > 0 THEN
COLOR GloMenu.cursorHi, GloMenu.cursorBack
LOCATE GloItem(currMenu, currItem).row, col + GloItem(currMenu, currItem).accessKey + 1
PRINT MID$(GloItem(currMenu, currItem).text, GloItem(currMenu, currItem).accessKey, 1);
END IF
END IF
END IF
MouseShow
RETURN
'===========================================================================
' This hides the cursor at the location CurrMenu,CurrItem.
'===========================================================================
MenuDoHideCursor:
MouseHide
IF currMenu <> 0 AND RTRIM$(GloItem(currMenu, currItem).text) <> "-" THEN
IF currItem = 0 THEN
SELECT CASE GloTitle(currMenu).state
CASE 0: COLOR GloMenu.disabled, GloMenu.back
CASE 1, 2: COLOR GloMenu.fore, GloMenu.back
CASE ELSE
END SELECT
LOCATE 1, GloTitle(currMenu).lColTitle
PRINT " "; RTRIM$(GloTitle(currMenu).text); " ";
IF GloTitle(currMenu).state > 0 THEN
COLOR GloMenu.highlight, GloMenu.back
LOCATE 1, GloTitle(currMenu).lColTitle + GloTitle(currMenu).accessKey
PRINT MID$(GloTitle(currMenu).text, GloTitle(currMenu).accessKey, 1);
END IF
ELSE
IF GloItem(currMenu, currItem).state = 2 THEN
chk$ = CHR$(175)
ELSE
chk$ = " "
END IF
SELECT CASE GloItem(currMenu, currItem).state
CASE 0: COLOR GloMenu.disabled, GloMenu.back
CASE 1, 2: COLOR GloMenu.fore, GloMenu.back
CASE ELSE
END SELECT
LOCATE GloItem(currMenu, currItem).row, GloTitle(currMenu).lColItem + 1
PRINT chk$; LEFT$(GloItem(currMenu, currItem).text, GloTitle(currMenu).itemLength); " ";
IF GloItem(currMenu, currItem).state > 0 THEN
COLOR GloMenu.highlight, GloMenu.back
LOCATE GloItem(currMenu, currItem).row, col + GloItem(currMenu, currItem).accessKey + 1
PRINT MID$(GloItem(currMenu, currItem).text, GloItem(currMenu, currItem).accessKey, 1);
END IF
END IF
END IF
MouseShow
RETURN
'===========================================================================
' Handles state where mouse is at row #1.
'===========================================================================
MenuDoGetMouseMenu:
'=======================================================================
' Computes the menu number based on mouse column location. Uses info
' calculated in MenuShow()
'=======================================================================
newMenu = CVI(MID$(GloMenu.menuIndex, mouseCol * 2 - 1, 2))
IF GloTitle(newMenu).state <> 1 THEN
newMenu = 0
END IF
'=======================================================================
' If new menu<>current menu, hide current menu, show new menu, assign new
' menu to current menu
'=======================================================================
IF newMenu <> currMenu THEN
GOSUB MenuDoHidePullDown
currMenu = newMenu
currItem = 0
GOSUB menuDoShowPullDown
END IF
RETURN
'===========================================================================
' Handles state where mouse is not in row #1. If a menu is down, it picks
' the proper menu item based on which row the mouse is located
'===========================================================================
MenuDoGetMouseItem:
'=======================================================================
' If pulldown, and mouse column is within the menu area, then compute new
' item based on computations done in MenuShow. If not in box, then new
' item = 0
'=======================================================================
IF pulldown THEN
IF mouseCol >= GloTitle(currMenu).lColItem AND mouseCol <= GloTitle(currMenu).rColItem AND mouseRow <= GloTitle(currMenu).lowestRow AND mouseRow - 2 <= MAXITEM THEN
newItem = GloItem(currMenu, mouseRow - 2).index
ELSE
newItem = 0
END IF
' ===================================================================
' If current item <> new item, hide old cursor, show new cursor,
' assign new item to current item.
' ===================================================================
IF currItem <> newItem THEN
IF currItem <> 0 THEN
GOSUB MenuDoHideCursor
END IF
currItem = newItem
GOSUB MenuDoShowCursor
END IF
END IF
RETURN
' ===========================================================================
' Handles state when MenuDo is in mouse mode, and mouse button is released.
' ===========================================================================
MenuDoMouseRelease:
menuMode = FALSE
' =======================================================================
' If no menu selected, then exit MenuDo returning 0s for menu and item
' =======================================================================
IF currMenu = 0 THEN
GloMenu.currMenu = 0
GloMenu.currItem = 0
MenuDoDone = TRUE
ELSE
' ===================================================================
' If menu is down, but no item is selected then
' if mouse is on the top row, simply gosub the MenuDoDown routine
' else hide menu then exit MenuDo returning 0's for menu and item
' ===================================================================
IF currItem = 0 THEN
IF mouseRow = 1 THEN
GOSUB menuDoDown
ELSE
GOSUB MenuDoHidePullDown
GloMenu.currMenu = 0
GloMenu.currItem = 0
MenuDoDone = TRUE
END IF
ELSE
' ===============================================================
' If current (menu,item)'s state is disabled, then just beep
' ===============================================================
IF GloItem(currMenu, currItem).state = 0 THEN
BEEP
' ===============================================================
' If current (menu,item)'s state is a line
' then exit MenuDo returning 0s for menu and item
' ===============================================================
ELSEIF RTRIM$(GloItem(currMenu, currItem).text) = "-" THEN
GOSUB MenuDoHidePullDown
GloMenu.currMenu = 0
GloMenu.currItem = 0
MenuDoDone = TRUE
ELSE
' ===========================================================
' Otherwise, selection must be valid, exit MenuDo, returning
' proper menu,item pair in the proper global variables
' ===========================================================
GOSUB MenuDoHidePullDown
GloMenu.currMenu = currMenu
GloMenu.currItem = currItem
MenuDoDone = TRUE
END IF
END IF
END IF
RETURN
' ==========================================================================
' This routine shows the menu bar's access keys
' ==========================================================================
MenuDoShowTitleAccessKeys:
MouseHide
COLOR GloMenu.highlight, GloMenu.back
FOR menu = 1 TO MAXMENU
IF GloTitle(menu).state = 1 THEN
LOCATE 1, GloTitle(menu).lColTitle + GloTitle(menu).accessKey
PRINT MID$(GloTitle(menu).text, GloTitle(menu).accessKey, 1);
END IF
NEXT menu
MouseShow
RETURN
' ===========================================================================
' This routine hides the menu bar's access keys
' ===========================================================================
MenuDoHideTitleAccessKeys:
MouseHide
COLOR GloMenu.fore, GloMenu.back
FOR menu = 1 TO MAXMENU
IF GloTitle(menu).state = 1 THEN
LOCATE 1, GloTitle(menu).lColTitle + GloTitle(menu).accessKey
PRINT MID$(GloTitle(menu).text, GloTitle(menu).accessKey, 1);
END IF
NEXT menu
MouseShow
RETURN
' ===========================================================================
' Waits for key press, then returns the key press. It also returns several
' tokens such as "menu", or "altReleased" in special cases. Read on...
' ===========================================================================
MenuDoGetKey:
DO
kbd$ = iNKEY$
' ===================================================================
' If ALT key pressed, then if it was a access key (Alt+A..) reduce
' the Alt+A to A.
' Also set the altPressed flags to reflect the current state of the
' ALT key.
' ===================================================================
IF GetShiftState(3) THEN
IF kbd$ = "" THEN
IF altWasReleased THEN
altWasPressedAgain = TRUE
END IF
ELSE
altWasPressedAgain = FALSE
kbd$ = AltToASCII(kbd$)
END IF
altWasReleased = FALSE
ELSE
' ===============================================================
' If ALT key is released (initially), then pressed, then released
' again with no other action in between, then return the
' token "altReleased"
' ===============================================================
IF altWasPressedAgain THEN
kbd$ = "altReleased"
altWasPressedAgain = FALSE
ELSE
' ===========================================================
' Based on the key that was pressed, return the proper token
' ===========================================================
altWasReleased = TRUE
SELECT CASE kbd$
CASE CHR$(27) + "": kbd$ = "escape"
CASE CHR$(32) + "": kbd$ = ""
CASE CHR$(13) + "": kbd$ = "enter"
CASE CHR$(0) + "H": kbd$ = "up"
CASE CHR$(0) + "P": kbd$ = "down"
CASE CHR$(0) + "K": kbd$ = "left"
CASE CHR$(0) + "M": kbd$ = "right"
CASE ELSE
IF LEN(kbd$) = 1 THEN
kbd$ = UCASE$(kbd$)
END IF
END SELECT
END IF
END IF
' ===================================================================
' If mouse button is pressed, it overrides all key actions, and
' the token "mouse" is returned
' ===================================================================
MousePoll mouseRow, mouseCol, lButton, rButton
IF lButton THEN
kbd$ = "mouse"
END IF
LOOP UNTIL kbd$ <> ""
RETURN
' ===========================================================================
' Handles the state where the up arrow is pressed. It searches for the
' first non empty, non "-" (dashed) item.
' ===========================================================================
MenuDoUp:
IF currItem <> 0 THEN
DO
currItem = (currItem + MAXITEM - 2) MOD MAXITEM + 1
LOOP UNTIL GloItem(currMenu, currItem).state >= 0 AND RTRIM$(GloItem(currMenu, currItem).text) <> "-"
END IF
RETURN
' ===========================================================================
' Handles 2 different states:
'
' State 1: Menu is open, and the down arrow is pressed.
'
' State 2: Any time a new menu is opened, and the top item
' is to be the current item. Specifically:
' - When no menu is opened, and the down arrow is pressed
' - When the mouse is released over the menu title
' - When a menu is opened, and the user hits right/left arrow
' - When enter is pressed while cursor is on title bar
' - When a access key is used on the title bar.
' ===========================================================================
menuDoDown:
DO
IF currItem = 0 THEN
GOSUB MenuDoHideTitleAccessKeys
GOSUB menuDoShowPullDown
currItem = (currItem) MOD MAXITEM + 1
ELSEIF currItem > 0 THEN
currItem = (currItem) MOD MAXITEM + 1
END IF
LOOP UNTIL GloItem(currMenu, currItem).state >= 0 AND RTRIM$(GloItem(currMenu, currItem).text) <> "-"
RETURN
' ===========================================================================
' Handles state when the left arrow is pressed. If a menu is down, it
' hides it. It then finds the first valid menu to the left. If the menu
' was initially down, then the new menu is pulled down as well
' ===========================================================================
MenuDoLeft:
IF pulldown THEN
GOSUB MenuDoHidePullDown
pulldown = TRUE
END IF
DO
currMenu = (currMenu + MAXMENU - 2) MOD MAXMENU + 1
LOOP UNTIL GloTitle(currMenu).state = 1
IF pulldown THEN
currItem = 0
GOSUB menuDoDown
END IF
RETURN
' ===========================================================================
' Handles state when the right arrow is pressed. If a menu is down, it
' hides it. It then finds the first valid menu to the right. If the menu
' was initially down, then the new menu is pulled down as well
' ===========================================================================
MenuDoRight:
IF pulldown THEN
GOSUB MenuDoHidePullDown
pulldown = TRUE
END IF
DO
currMenu = (currMenu) MOD MAXMENU + 1
LOOP UNTIL GloTitle(currMenu).state = 1
IF pulldown THEN
currItem = 0
GOSUB menuDoDown
END IF
RETURN
' ===========================================================================
' Handles state when the ESC key is pressed. First hides the menu, and
' then exits menuDo, returning 0's in the proper global variables
' ===========================================================================
MenuDoEscape:
GOSUB MenuDoHidePullDown
GloMenu.currMenu = 0
GloMenu.currItem = 0
MenuDoDone = TRUE
RETURN
' ===========================================================================
' Handles state when Enter is pressed. If on a valid item, return the
' proper (menu,item) pair and exit. Else beep. If on a valid menu
' this will open the menu by calling MenuDoDown
' ===========================================================================
MenuDoEnter:
IF currItem = 0 THEN
IF GloTitle(currMenu).state = 0 THEN
BEEP
ELSE
GOSUB menuDoDown
END IF
ELSE
IF GloItem(currMenu, currItem).state <= 0 THEN
BEEP
ELSE
GOSUB MenuDoHidePullDown
GloMenu.currMenu = currMenu
GloMenu.currItem = currItem
MenuDoDone = TRUE
END IF
END IF
RETURN
' ===========================================================================
' If ALT pressed and released with nothing else happening in between, it
' will exit if no menu is open, or close the menu if one is open.
' ===========================================================================
MenuDoAltReleased:
IF pulldown THEN
GOSUB MenuDoHidePullDown
currItem = 0
GOSUB MenuDoShowTitleAccessKeys
ELSE
GloMenu.currMenu = 0
GloMenu.currItem = 0
MenuDoDone = TRUE
END IF
RETURN
' ===========================================================================
' If mouse is pressed while in keyboard mode, this routine assigns
' TRUE to MouseMode, resets the item, and hides the access keys
' ===========================================================================
MenuDoMousePress:
mouseMode = TRUE
currItem = 0
IF NOT pulldown THEN
GOSUB MenuDoHideTitleAccessKeys
END IF
RETURN
' ===========================================================================
' If a access key is pressed
' ===========================================================================
MenuDoAccessKey:
' =======================================================================
' If an access key is pressed
' If no menu selected, search titles for matching access key, and open
' than menu.
' =======================================================================
IF currItem = 0 THEN
newMenu = (currMenu + MAXMENU - 2) MOD MAXMENU + 1
loopEnd = (currMenu + MAXMENU - 2) MOD MAXMENU + 1
DO
newMenu = (newMenu) MOD MAXMENU + 1
LOOP UNTIL (UCASE$(MID$(GloTitle(newMenu).text, GloTitle(newMenu).accessKey, 1)) = kbd$ AND GloTitle(newMenu).state = 1) OR newMenu = loopEnd
IF kbd$ = UCASE$(MID$(GloTitle(newMenu).text, GloTitle(newMenu).accessKey, 1)) THEN
currMenu = newMenu
GOSUB menuDoDown
END IF
ELSE
' ===================================================================
' If menu is selected, search items for matching access key, and
' select that (menu,item) and exit MenuDo if item is enabled
' ===================================================================
newItem = (currItem + MAXITEM - 2) MOD MAXITEM + 1
loopEnd = (currItem + MAXITEM - 2) MOD MAXITEM + 1
DO
newItem = (newItem) MOD MAXITEM + 1
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
IF kbd$ = UCASE$(MID$(GloItem(currMenu, newItem).text, GloItem(currMenu, newItem).accessKey, 1)) THEN
currItem = newItem
IF GloItem(currMenu, currItem).state <= 0 THEN
BEEP
ELSE
GOSUB MenuDoHidePullDown
GloMenu.currMenu = currMenu
GloMenu.currItem = currItem
MenuDoDone = TRUE
END IF
END IF
END IF
RETURN
' ===========================================================================
' Draws the menu -- only if menu is enabled.
' ===========================================================================
menuDoShowPullDown:
IF currMenu <> 0 AND GloTitle(currMenu).state = 1 THEN
' ===================================================================
' Copies the background if this is the first time this particular
' menu is being drawn
' ===================================================================
MouseHide
IF NOT copyFlag(currMenu) THEN
IF GloTitle(currMenu).rColItem - GloTitle(currMenu).lColItem < LEN(GloTitle(currMenu).text) THEN
GloTitle(currMenu).rColItem = GloTitle(currMenu).lColItem + LEN(GloTitle(currMenu).text)
END IF
GetBackground 1, GloTitle(currMenu).lColItem, GloTitle(currMenu).lowestRow, GloTitle(currMenu).rColItem + 2, buffer$(currMenu)
copyFlag(currMenu) = TRUE
END IF
' ===================================================================
' Draw the menu, this is pretty straight forward
' ===================================================================
pulldown = TRUE
length = GloTitle(currMenu).itemLength
IF length = 0 THEN length = 6
lowestRow = 3
col = GloTitle(currMenu).lColItem
COLOR GloMenu.cursorFore, GloMenu.cursorBack
LOCATE 1, GloTitle(currMenu).lColTitle
PRINT " "; RTRIM$(GloTitle(currMenu).text); " ";
COLOR GloMenu.fore, GloMenu.back
LOCATE 2, col
PRINT "┌"; STRING$(length + 2, "─"); "┐"
FOR item = 1 TO MAXITEM
IF GloItem(currMenu, item).state >= 0 THEN
IF GloItem(currMenu, item).state = 2 THEN
chk$ = CHR$(175)
ELSE
chk$ = " "
END IF
LOCATE GloItem(currMenu, item).row, col
COLOR GloMenu.fore, GloMenu.back
IF RTRIM$(GloItem(currMenu, item).text) = "-" THEN
PRINT "├"; STRING$(length + 2, "─"); "┤"
ELSE
PRINT "│"; chk$;
IF GloItem(currMenu, item).state > 0 THEN
COLOR GloMenu.fore, GloMenu.back
ELSE
COLOR GloMenu.disabled, GloMenu.back
END IF
PRINT LEFT$(GloItem(currMenu, item).text + SPACE$(20), length);
COLOR GloMenu.fore, GloMenu.back
PRINT " │";
IF GloItem(currMenu, item).state > 0 THEN
COLOR GloMenu.highlight, GloMenu.back
LOCATE GloItem(currMenu, item).row, col + GloItem(currMenu, item).accessKey + 1
PRINT MID$(GloItem(currMenu, item).text, GloItem(currMenu, item).accessKey, 1);
END IF
END IF
lowestRow = GloItem(currMenu, item).row + 1
END IF
NEXT item
COLOR GloMenu.fore, GloMenu.back
LOCATE lowestRow, col
PRINT "└"; STRING$(length + 2, "─"); "┘";
rCol = col + length + 5
AttrBox 3, rCol - 1, lowestRow, rCol, 8
AttrBox lowestRow + 1, col + 2, lowestRow + 1, rCol, 8
END IF
MouseShow
RETURN
' ===========================================================================
' Replace the background over the menu
' ===========================================================================
MenuDoHidePullDown:
IF pulldown THEN
MouseHide
PutBackground 1, GloTitle(currMenu).lColItem, buffer$(currMenu)
MouseShow
pulldown = FALSE
END IF
RETURN
END SUB
SUB MenuEvent
' =======================================================================
' If ALT key is pressed, let MenuDo take over. NOTE: This will
' not call MenuDo if the ALT key has not been released at least
' once since the last time MenuDo was called. This prevents the menu
' from flashing if the user simply holds down the ALT key.
' =======================================================================
IF GetShiftState(3) THEN
IF GloMenu.altKeyReset THEN
MenuDo
GloMenu.altKeyReset = FALSE
END IF
ELSE
GloMenu.altKeyReset = TRUE
END IF
' =======================================================================
' Call MenuDo if the mouse button is down, and the cursor is on the top row
' =======================================================================
MousePoll mouseRow, mouseCol, lButton, rButton
IF mouseRow = 1 AND lButton THEN
MenuDo
END IF
END SUB
SUB MenuInit
' =======================================================================
' Initialize global menu arrays
' =======================================================================
FOR menu = 1 TO MAXMENU
GloTitle(menu).text = ""
GloTitle(menu).state = -1 'state of -1 means "empty"
GloTitle(menu).rColItem = 0 'These get set in MenuShow
GloTitle(menu).lColItem = 0 ' |
GloTitle(menu).rColTitle = 0 ' |
GloTitle(menu).lColTitle = 0 ' |
GloTitle(menu).itemLength = 0 ' |
GloTitle(menu).accessKey = 1 'Initial AccessKey of 1
FOR item = 1 TO MAXITEM
GloItem(menu, item).text = ""
GloItem(menu, item).state = -1 'state of -1 means "empty"
GloItem(menu, item).index = 0 'These get set in MenuShow
GloItem(menu, item).row = 0 ' |
GloItem(menu, item).accessKey = 1 'Initial AccessKey of 1
NEXT item
NEXT menu
' =======================================================================
' Initialize mouse
' =======================================================================
MouseInit
' =======================================================================
' Set initial state of ALT key to "reset"
' Clear out shortcut key index
' Set initial state of menu to ON
' =======================================================================
GloMenu.altKeyReset = TRUE
GloMenu.shortcutKeyIndex = STRING$(100, 0)
GloMenu.MenuOn = TRUE
GloMenu.fore = 0
GloMenu.back = 7
GloMenu.highlight = 15
GloMenu.disabled = 8
GloMenu.cursorFore = 7
GloMenu.cursorBack = 0
GloMenu.cursorHi = 15
END SUB
FUNCTION MenuInkey$ STATIC
' =======================================================================
' Scan keyboard, return KBD$ by default -- unless it is over written below
' =======================================================================
kbd$ = INKEY$
MenuInkey$ = kbd$
' =======================================================================
' Check if KBD$ matches a shortcut key. If it does, return "menu" instead
' of the key that was pressed
' =======================================================================
ShortCutKeyEvent kbd$
IF MenuCheck(2) THEN
MenuInkey$ = "menu"
ELSE
' ===================================================================
' Call menu event, which looks at mouse, and state of ALT key
' If a menu item is selected, return "menu" instead of KBD$
' ===================================================================
MenuEvent
IF MenuCheck(2) THEN
MenuInkey$ = "menu"
END IF
END IF
END FUNCTION
SUB MenuItemToggle (menu, item)
IF item >= 0 AND menu >= 1 AND item <= MAXITEM AND menu <= MAXMENU THEN
IF item = 0 OR GloItem(menu, item).state < 1 OR GloItem(menu, item).state > 2 THEN
'| --- Modified to Support OS/2 ---
'| Changed SOUND to BSound which uses the DOSSOUND function
BSOUND 2000, 40
ELSE
GloItem(menu, item).state = 3 - GloItem(menu, item).state
END IF
END IF
END SUB
DEFSNG A-Z
SUB MenuOff
' =======================================================================
' Simply assigns FALSE to the proper global variable
' =======================================================================
GloMenu.MenuOn = FALSE
END SUB
DEFINT A-Z
SUB MenuOn
' =======================================================================
' Simply assigns TRUE to the proper global variable
' =======================================================================
GloMenu.MenuOn = TRUE
END SUB
SUB MenuPreProcess STATIC
currCol = 2 'Represents the col where first menu title is located
' =======================================================================
' Menu index is a fast way of decoding which menu the mouse cursor
' is pointing to based on the col of the cursor. See MENU.BI for details.
' =======================================================================
GloMenu.menuIndex = STRING$(160, 0)
' =======================================================================
' Process each menu, one at a time
' =======================================================================
FOR menu = 1 TO MAXMENU
' ===================================================================
' If state is empty, or text is "" then clear out data for that menu
' ===================================================================
IF GloTitle(menu).state < 0 OR LEN(RTRIM$(GloTitle(menu).text)) = 0 THEN
GloTitle(menu).rColItem = 0
GloTitle(menu).lColItem = 0
GloTitle(menu).rColTitle = 0
GloTitle(menu).lColTitle = 0
GloTitle(menu).itemLength = 0
GloTitle(menu).state = -1
ELSE
' ===============================================================
' else, assign data about the column location to the global storage
' ===============================================================
GloTitle(menu).lColTitle = currCol
GloTitle(menu).rColTitle = currCol + LEN(RTRIM$(GloTitle(menu).text)) + 1
GloTitle(menu).lColItem = currCol - 1
IF GloTitle(menu).rColTitle > MAXCOL THEN
BEEP: CLS : PRINT "Menu bar longer than screen! Cannot function!"
END
END IF
' ===============================================================
' Update the index about where the menu is located, increment
' currCol
' ===============================================================
FOR index = currCol TO currCol + LEN(RTRIM$(GloTitle(menu).text)) + 1
MID$(GloMenu.menuIndex, index * 2 - 1, 2) = MKI$(menu)
NEXT index
currCol = currCol + LEN(RTRIM$(GloTitle(menu).text)) + 2
' ===============================================================
' Process the items in the menu, computing the
' longest item, and preparing the row index
' ===============================================================
GloTitle(menu).itemLength = 0
currRow = 3
iFlag = FALSE
FOR item = 1 TO MAXITEM
GloItem(menu, currRow - 2).index = 0
IF GloItem(menu, item).state >= 0 THEN
GloItem(menu, currRow - 2).index = item
GloItem(menu, item).row = currRow
currRow = currRow + 1
IF LEN(RTRIM$(GloItem(menu, item).text)) > GloTitle(menu).itemLength THEN
GloTitle(menu).itemLength = LEN(RTRIM$(GloItem(menu, item).text))
END IF
iFlag = TRUE
END IF
NEXT item
' ===============================================================
' If all items were empty, disable the menu itself
' else, assign the longest length to the proper variable
' ===============================================================
IF NOT iFlag THEN
GloTitle(menu).state = 0
ELSE
GloTitle(menu).rColItem = GloTitle(menu).lColItem + GloTitle(menu).itemLength + 3
IF GloTitle(menu).rColItem > MAXCOL - 2 THEN
diff = GloTitle(menu).rColItem - (MAXCOL - 2)
GloTitle(menu).rColItem = GloTitle(menu).rColItem - diff
GloTitle(menu).lColItem = GloTitle(menu).lColItem - diff
END IF
END IF
END IF
GloTitle(menu).lowestRow = currRow + 1
NEXT menu
END SUB
SUB MenuSet (menu, item, state, text$, accessKey) STATIC
IF accessKey > LEN(text$) THEN accessKey = LEN(text$)
IF item >= 0 AND menu >= 1 AND item <= MAXITEM AND menu <= MAXMENU THEN
' ===================================================================
' Assign parameters to proper global menu variables
' ===================================================================
IF item = 0 THEN
IF state < -1 OR state > 1 THEN
BSOUND 3000, 40 '| --- Modified to Support OS/2 ---
ELSE
GloTitle(menu).text = text$
GloTitle(menu).state = state
GloTitle(menu).accessKey = accessKey
END IF
ELSE
IF state < -1 OR state > 2 THEN
BSOUND 4000, 40 '| --- Modified to Support OS/2 ---
ELSE
GloItem(menu, item).text = text$
GloItem(menu, item).state = state
GloItem(menu, item).accessKey = accessKey
END IF
END IF
END IF
END SUB
SUB MenuSetState (menu, item, state) STATIC
' =======================================================================
' Assign parameters to proper global menu variables
' =======================================================================
IF item = 0 THEN
IF state < 0 OR state > 1 OR GloTitle(menu).state < 0 THEN
BSOUND 5000, 40 '| --- Modified to Support OS/2 ---
ELSE
GloTitle(menu).state = state
END IF
ELSE
IF state < 0 OR state > 2 OR GloItem(menu, item).state < 0 THEN
BSOUND 6000, 40 '| --- Modified to Support OS/2 ---
ELSE
GloItem(menu, item).state = state
END IF
END IF
END SUB
DEFSNG A-Z
SUB MenuShow
' =======================================================================
' This section actually prints the menu on the screen
' =======================================================================
MouseHide '| --- Modified to Support OS/2 ---
COLOR GloMenu.fore, GloMenu.back
LOCATE 1, 1
PRINT SPACE$(MAXCOL);
FOR menu = 1 TO MAXMENU
SELECT CASE GloTitle(menu).state
CASE 0:
COLOR GloMenu.disabled, GloMenu.back
LOCATE 1, GloTitle(menu).lColTitle + 1
PRINT RTRIM$(GloTitle(menu).text$);
CASE 1:
COLOR GloMenu.fore, GloMenu.back
LOCATE 1, GloTitle(menu).lColTitle + 1
PRINT RTRIM$(GloTitle(menu).text$);
CASE ELSE
END SELECT
NEXT menu
MouseShow '| --- Modified to Support OS/2 ---
END SUB
DEFINT A-Z
SUB ShortCutKeyDelete (menu, item) STATIC
'=======================================================================
' Search through shortcut key index until the menu,item pair is found
' or the end of the list is reached.
'=======================================================================
ptr = -1
DO
ptr = ptr + 1
temp = CVI(MID$(GloMenu.shortcutKeyIndex, ptr * 4 + 1, 2))
testMenu = INT(temp / 256)
testItem = INT(temp MOD 256)
LOOP UNTIL (menu = testMenu AND item = testItem) OR testMenu = 0 AND testItem = 0 OR ptr = 25
'=======================================================================
' If a match is found, delete the shortcut key by squeezing out the four
' bytes that represents the shortcut key, and adding four chr$(0) at the
' end.
'=======================================================================
IF menu = testMenu AND item = testItem THEN
GloMenu.shortcutKeyIndex = LEFT$(GloMenu.shortcutKeyIndex, ptr * 4) + RIGHT$(GloMenu.shortcutKeyIndex, 96 - ptr * 4) + STRING$(4, 0)
END IF
END SUB
SUB ShortCutKeyEvent (theKey$)
'=======================================================================
' If menu event trapping turned off, return immediately
'=======================================================================
IF NOT GloMenu.MenuOn THEN
EXIT SUB
END IF
'=======================================================================
' Make sure the length of theKey$ is two bytes by adding a chr$(0) if
' necessary. If the length is > 2, make it null.
'=======================================================================
SELECT CASE LEN(theKey$)
CASE 1
theKey$ = theKey$ + CHR$(0)
CASE 2
CASE ELSE
theKey$ = ""
END SELECT
'=======================================================================
' Search the shortcut key list for a match -- only if theKey$ is valid.
'=======================================================================
IF theKey$ <> "" THEN
ptr = -1
DO
ptr = ptr + 1
testKey$ = MID$(GloMenu.shortcutKeyIndex, ptr * 4 + 3, 2)
LOOP UNTIL theKey$ = testKey$ OR testKey$ = STRING$(2, 0) OR ptr = 25
'===================================================================
' If match is found, make sure menu choice is valid (state > 0)
' If so, assign the proper global variables.
'===================================================================
IF theKey$ = testKey$ THEN
temp = CVI(MID$(GloMenu.shortcutKeyIndex, ptr * 4 + 1, 2))
tempMenu = INT(temp / 256)
tempItem = INT(temp MOD 256)
IF GloItem(tempMenu, tempItem).state > 0 THEN
GloMenu.currMenu = tempMenu
GloMenu.currItem = tempItem
END IF
END IF
END IF
END SUB
SUB ShortCutKeySet (menu, item, shortcutKey$)
'=======================================================================
' Make sure the length of theKey$ is two bytes by adding a chr$(0) if
' necessary. If the length is >2, make it null.
'=======================================================================
SELECT CASE LEN(shortcutKey$)
CASE 1
shortcutKey$ = shortcutKey$ + CHR$(0)
CASE 2
CASE ELSE
shortcutKey$ = ""
END SELECT
'=======================================================================
' First delete the shortcut key, just in case it already exists, and then
' and the shortcut key to the front of the shortcut key index string.
'=======================================================================
ShortCutKeyDelete menu, item
IF shortcutKey$ <> "" THEN
newKey$ = MKI$(menu * 256 + item) + shortcutKey$
GloMenu.shortcutKeyIndex = newKey$ + LEFT$(GloMenu.shortcutKeyIndex, 396)
END IF
END SUB