home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 17
/
CD_ASCQ_17_101194.iso
/
vrac
/
menusys.zip
/
MENUSYS.BAS
< prev
next >
Wrap
BASIC Source File
|
1994-08-07
|
63KB
|
1,413 lines
DEFINT A-Z
DECLARE SUB BlkEdit (Txt$(), LCol, RCol, SRow, ERow, KeyCode)
DECLARE SUB DialogBox (Ddflts$, Dsin$, Dsout$, SelKey, DBCode)
DECLARE SUB MainCalc ()
DECLARE SUB SetUpPgm ()
DECLARE SUB ScrnCopy (Src, Dst)
DECLARE SUB BoxDisplay (Nitm, Nstrt, Txt$(), Ctrl, SDLin, ColCod$, Shdw, SelKey)
DECLARE SUB KeyPress (KeyCode)
DECLARE SUB AKMnuRead (MnuCtrl(), MnuItm1$(), MnuItm2$())
DECLARE SUB AKMnuSet (MnuCtrl(), MnuItm1$(), MnuItm2$())
DECLARE SUB AKMnuCtrl (KeyCode, MnuCtrl(), MnuItm1$(), MnuItm2$(), SelKey)
DECLARE SUB BoxDraw (LCol, RCol, SRow, ERow, BFil, Brdr, FGrnd, BGrnd, Shdw)
DECLARE SUB CenterLin (Row, LCol, RCol, Text$)
DECLARE SUB StrngBar (Row, Text$)
'$DYNAMIC 'Not needed, but common in pgms
'Example pull-down menu system set up in dummy program structure to demonstate use.
'There is a typical horizontal key word menu across top with highlighted letters.
'Alt-highlight key calls a vertical box of menu items.
'F10 + letter as in CUA compliant menus also selects vertical menu box.
'Select desired menu item via bounce (highlite) bar or indicated highlite letter.
'In general <Home>, PgUp, Ctrl-U(p), <End>, arrow keys, <space>, etc. control bounce bar.
'Program control is passed to menu items based on a convenient numerical code in MainCalc.
'Can be set up for optional Lotus-style "/" + highlight letter activation of menu.
'The entire menu system is set up by use of DATA statements as shown below.
'All but routines MainCalc and SetUpPgm are designed to be used as is in your programs.
'The AKMnu routines go together and require the Box routines, ScrnCopy, and KeyPress
'Modify as you need for your programs. Polling mouse buttons during KeyPress and using
' menu item row/column arrays to translate mouse cursor position into item selection
' can be done as a QB programming challenge, if you are rodent inclined.
' Brian Dinsmoor 76675,1606
TYPE PgmColors ' Text SCREEN color variables used to display menu system
fg AS INTEGER 'Foregrnd
bg AS INTEGER 'Backgrnd
bt AS INTEGER 'Border/Title
wf AS INTEGER 'Window/Msg Box display foregrnd
wb AS INTEGER 'Window/Msg Box display backgrnd
mf AS INTEGER 'Menu foregrnd > key
mb AS INTEGER 'Menu backgrnd > menu
hk AS INTEGER 'HiLite key > colors
END TYPE
TYPE SystmData
vid AS INTEGER 'Type of video adapter by integer code
END TYPE
COMMON SHARED pc AS PgmColors, Sdata AS SystmData
CALL SetUpPgm 'Begin execution with setup routine
'BELOW IS DATA ARRAY OF INPUT FOR MENU SYSTEM. INCLUDE IN MAIN MODULE.
' Note where " " is used to be sure the BASIC interpreter properly defines variables.
MainMenu1:
DATA 2,6,5,9,FEVSR*,File,Edit,View,Search,Run," F1 = Help"
DATA 9,NOMS-LU-A,New,Open,Merge,Save,-,Load,Unload,-,Append
DATA 6,UTCP-B,Undo,CuT,Copy,Paste,-,Block
DATA 7,SNP-I-O,Subs,Next,SPlit,-,Include,-,Options ...
DATA 4,FSRC,Find,Selected,Repeat,Change
DATA 6,SRCM-K,Start,Restart,Continue,Modify ...,-,MaKe
MainDialog1: 'First Dialog Box
DATA < View Options >,10
DATA 1,S,Search Directory,20
DATA 2,V,Auto View Files,6,WK1/WK2/WQ1/DBF/DIF/SLK
DATA 6," "
DATA 3,D,"Display Window:",3,Primary/Vert Splt/Hor Splt
DATA 4,y,Synch Scroll
DATA 4,A,Auto Save
DATA 4,H,Auto Highlight
DATA 6," "
DATA 5,UFQ,3,Update/DeFault/Quit
DATA 7,"C:\DUMMY\*.DOC/SLK/3/1/0/0/0"
MainDialog2: 'Second Dialog Box
DATA , 8
DATA 6,"Modem Default ... "
DATA 2,S,Speed,7,300/1200/2400/4800/9600/14400/19200
DATA 3,D,"Data Bits:",2,7/8
DATA 3,P,"Parity:",3,Odd/Even/None
DATA 3,B,"Stop Bits:",3,0/1/2
DATA 2,T,Terminal,4,ANSI/TTY/VT52/VT100
DATA 5,C,1,Connect
DATA 7,"2400/1/2/2/TTY/0"
' |
' Intro screens for program
' |
' Have arrived at program section with menu system
' |
CALL MainCalc
' |
' Closing of program (update defaults, erase temp files, etc.)
' |
EndPgm:
COLOR 7, 0 'Reset and exit
CLS
END
REM $STATIC
SUB AKMnuCtrl (KeyCode, MnuCtrl(), MnuItm1$(), MnuItm2$(), SelKey) STATIC
'Vertical Window Menu generator with highlight key option for selections.
'Alt-Alpha key or F10(+ highlight letter for CUA standard) selections trapped to this routine.
'Can trap "/" for Lotus style menu system as well. Can modify AKMnu routines to display
' stacked horizontal menus as in Lotus 123.
'Calls BoxDraw for specified horizontal category and displays subordinate Items in box.
'Cursor keys control highlight bar and <CR> or highlight letter selects item.
' KeyCode = alt-key menu category selected on input. Returns as
' horizontal number category or 0 if error.
' MnuCtrl, MnuItm$ arrays - see AKMnuRead subprogram for definitions.
' SelKey = vertical item number selected for a selected horizontal category("cat").
' Can be: 0 for selected KeyCode item with no vertical menu
' -1 for no valid trapped highlite key
' -2 for <Esc> without selection
'Assumes use of active screen page 0 and stores screens in pages 1, 2.
'Uses pc.mf, .mb, .hk menu colors.
'Requires use of ScrnCopy, KeyPress, BoxDraw
SELECT CASE KeyCode 'Extract letter from alt key press
CASE -25 TO -16
letter$ = MID$("POIUYTREWQ", KeyCode + 26, 1)
CASE -38 TO -30
letter$ = MID$("LKJHGFDSA", KeyCode + 39, 1)
CASE -50 TO -44
letter$ = MID$("MNBVCXZ", KeyCode + 51, 1)
CASE IS = -68 'F10 key trap for CUA menu. Can trap 47 ("/") for Lotus style
CALL KeyPress(KeyCode) 'Modify here if F10 or / opens first category upon <CR>
IF KeyCode < 65 OR KeyCode > 122 THEN 'Must follow with letter
letter$ = " "
ELSE
letter$ = UCASE$(CHR$(KeyCode))
END IF
CASE ELSE
KeyCode = 0: SelKey = 0: EXIT SUB 'Return if error
END SELECT
cat = INSTR(MnuItm1$(1), letter$) 'Find in highlight string
IF cat = 0 THEN
KeyCode = 0: SelKey = -1: EXIT SUB
END IF
IF cat > MnuCtrl(3) THEN
KeyCode = cat: SelKey = 0: EXIT SUB
END IF
AKMCLoop1:
nv = MnuCtrl(MnuCtrl(2) + 3 + cat) 'Extract location and menu parameters
Row = MnuCtrl(1)
col = MnuCtrl(cat + 3) - 1
hkver$ = MnuItm1$(MnuCtrl(2) + 1 + cat)
CALL ScrnCopy(0, 1) 'Save current screen
LOCATE Row, col, 0 'Highlight horizontal item
COLOR pc.mb, pc.mf
PRINT " "; MnuItm1$(cat + 1); " ";
lmax = 0: SelKey = 1 'Start with first item
FOR i = 1 TO nv 'Find longest item to set width
a = LEN(MnuItm2$(cat, i))
IF a > lmax THEN lmax = a
NEXT i
lmax = lmax + 2 'Draw filled box
CALL BoxDraw(col, col + lmax + 1, Row + 1, Row + nv + 2, 1, 1, pc.mf, pc.mb, 1)
Row = Row + 1: col = col + 1 'Relocate for menu items
FOR i = 1 TO nv 'Fill in Items 1 thru n
LOCATE Row + i, col
IF MnuItm2$(cat, i) = "-" THEN 'If in string, print group divider
PRINT STRING$(lmax, 196);
ELSE
PRINT " " + MnuItm2$(cat, i);
a$ = MID$(hkver$, i, 1) 'Find and print highlight letter
b = INSTR(MnuItm2$(cat, i), a$)
IF b > 0 THEN
COLOR pc.hk
LOCATE , col + b
PRINT a$;
COLOR pc.mf
END IF
END IF
NEXT i
CALL ScrnCopy(0, 2) 'Save screen with highlighted menu item
AKMCLoop2: 'Set up loop for selecting menu items
COLOR pc.mb, pc.mf 'Highlight SelKey item
LOCATE Row + SelKey, col
PRINT " "; MnuItm2$(cat, SelKey); TAB(col + lmax);
a$ = MID$(hkver$, SelKey, 1) 'Need highlight letter in Item
b = INSTR(MnuItm2$(cat, SelKey), a$)
IF b > 0 THEN
COLOR pc.hk
LOCATE , col + b
PRINT a$;
END IF
AKMCLoop3: 'Set up loop for bad key presses
CALL KeyPress(KeyCode)
SELECT CASE KeyCode 'Process key stroke code
CASE IS = 27 'Esc
KeyCode = 0: SelKey = -2
COLOR pc.fg, pc.bg: CALL ScrnCopy(1, 0)
EXIT SUB
CASE IS = 13
KeyCode = cat 'Return
COLOR pc.fg, pc.bg: CALL ScrnCopy(1, 0)
EXIT SUB
CASE IS = -71 'Home
SelKey = 1
CASE IS = -79 'End
SelKey = nv
CASE IS = -72, -22 'Up Arrow, Alt-U
SelKey = SelKey - 1
IF SelKey = 0 THEN SelKey = nv
IF MID$(MnuItm2$(cat, SelKey), 1, 1) = "-" THEN SelKey = SelKey - 1
CASE IS = -80, -32, 32 'Down Arrow, Alt-D, space
SelKey = SelKey + 1
IF SelKey > nv THEN SelKey = 1
IF MID$(MnuItm2$(cat, SelKey), 1, 1) = "-" THEN SelKey = SelKey + 1
CASE IS = -75, -38 'Left Arrow, Alt-L
cat = cat - 1
IF cat < 1 THEN cat = MnuCtrl(3)
CALL ScrnCopy(1, 0)
GOTO AKMCLoop1:
CASE IS = -77, -19 'Right Arrow
cat = cat + 1
IF cat > MnuCtrl(3) THEN cat = 1
CALL ScrnCopy(1, 0)
GOTO AKMCLoop1:
CASE 65 TO 90, 97 TO 122 'If pressed highlight letter, exit
FOR i = 1 TO nv
IF UCASE$(MID$(hkver$, i, 1)) = UCASE$(CHR$(KeyCode)) THEN
KeyCode = cat: SelKey = i
COLOR pc.fg, pc.bg: CALL ScrnCopy(1, 0)
EXIT SUB
END IF
NEXT i 'Note no-action key presses
GOTO AKMCLoop3:
CASE ELSE
GOTO AKMCLoop3:
END SELECT
CALL ScrnCopy(2, 0)
GOTO AKMCLoop2:
END SUB
SUB AKMnuRead (MnuCtrl(), MnuItm1$(), MnuItm2$()) STATIC
'Reads setup for horizontal Alt-Key (or F10+letter) Menu with pull-down vertical menus
' under some or all of the horizontal items. Will not work without at least one vertical menu item.
'Can modify to trap "/" for Lotus style stacked horizontal menus
'Use DATA statements in module code to match with READ statements below.
' Row = starting row for horizontal menu display
' NHor = number of items in horizontal menu
' NVerCat = number of horizontal categories (left justified) having vertical menus
' NMaxVer = maximum number of items in vertical menu (including dividers) for sizing item array
' HKHor$ = highlight key string for horizontal menu. Highlite letters in menu items must be in caps.
' Use "*" character for no highlite letter for a menu item.
' MnuCtrl(1) = row for horizontal menu. start vertical window one row lower.
' (2) = number of horizontal menu items.
' (3) = number of horizontal items with vertical menus (left-justified).
' (4-MnuCtrl(2)) = starting column positions of horizontal items.
' (last MnuCtrl(3)) = number of items in each vertical menu including divider.
' A "-" character for an item means a divider for a logical group of
' selectable menu items.
' MnuItm1$(1) = string containing highlight keys for horizontal menu.
' (2-MnuCtrl(2)) = Horizontal menu items displayed on "row".
' (last MnuCtrl(3)) = highlight key strings for each vertical menu.
' "-" matches the dash divider. "*" means no highlight for that item.
' MnuItm2$(i,j) = vertical items (j) for each horizontal menu category (i).
'No vertical items for a selectable (by highlite key) horizontal category can be used.
' To make these Alt-Alpha keypresses return from AKMnuCtrl as those with vertical
' menus, the DATA statement needs to show one dummy vertical menu item that is
' blank as in: DATA 1,*," " Non-selectable horizontal categories need to be at
' the right beyond NVerCat thru NHor.
READ Row, NHor, NVerCat, NMaxVer, HKHor$
REDIM MnuCtrl(1 TO NHor + NVerCat + 3), MnuItm1$(1 TO NHor + NVerCat + 1)
REDIM MnuItm2$(1 TO NVerCat, 1 TO NMaxVer)
FOR i = 2 TO NHor + 1
READ MnuItm1$(i)
NEXT i
MnuItm1$(1) = HKHor$
FOR i = 1 TO NVerCat
READ MnuCtrl(3 + NHor + i), MnuItm1$(1 + NHor + i)
FOR j = 1 TO MnuCtrl(3 + NHor + i)
READ MnuItm2$(i, j)
NEXT j
NEXT i
col = 3 'Calculate column positions for menus
FOR i = 1 TO NHor
MnuCtrl(3 + i) = col
t = LEN(MnuItm1$(i + 1))
col = col + t + 2
NEXT i
MnuCtrl(1) = Row: MnuCtrl(2) = NHor: MnuCtrl(3) = NVerCat
END SUB
SUB AKMnuSet (MnuCtrl(), MnuItm1$(), MnuItm2$()) STATIC
'Alt-Key Menu bar generator for use in pull down menu system.
'Builds menu bar with Alt-key highlight letter for selected category.
'Use menu forgrnd (.mf) and backgrnd (.mb) with highlight (.hk) key colors.
' MnuCtrl, MnuItm$ arrays - see AKMnuRead subprogram for definitions
COLOR pc.mf, pc.mb
LOCATE MnuCtrl(1), 1, 0 'Locate on desired row
PRINT SPACE$(80);
FOR i = 1 TO MnuCtrl(2)
LOCATE , MnuCtrl(3 + i)
t = LEN(MnuItm1$(1 + i))
a$ = MID$(MnuItm1$(1), i, 1)
FOR j = 1 TO t 'Print menu item with highlight key
b$ = MID$(MnuItm1$(1 + i), j, 1)
IF b$ = a$ THEN
COLOR pc.hk
PRINT a$;
COLOR tmp
ELSE
PRINT b$;
END IF
NEXT j
NEXT i
COLOR pc.fg, pc.bg
END SUB
SUB BlkEdit (Txt$(), LCol, RCol, SRow, ERow, KeyCode) STATIC
'General Purpose Text Block Editing Routine.
'Modify usable keys and keys that exit as needed.
' Txt$ = array of ASCII strings that make up block text
' LCol = starting left column for block
' RCol = ending right column
' SRow = starting row for block
' ERow = ending row
'Requires KeyPress(KeyCode) subroutine:
' KeyCode = keycode for key press exiting subroutine. if just want to print
' block and exit, set this = 999 on calling BlkEdit.
'Comment out and/or modify KeyPress select case items to control exit from
' block. This routine can be readily used as a line or field input editor. Call
' BlkEdit from another routine that filters (min, max, select from table, etc) user
' input. If you already have a page text editor with wordwrap, you can scale this
' routine down to a single line field editor and simplify the coding.
'Note that the LOCATE cursor height control will not work on some mono and CGA displays.
' Insert/Overtype still works. Since this often involves LCD laptops, leaving a large
' cursor is not undesirable.
REDIM a$(SRow TO ERow)
IF ABS(Sdata.vid) = 1 THEN ScnLins = 7 ELSE ScnLins = 13
' IF Sdata.vid = 0 THEN ScnLins = 13 ELSE ScnLins = 7 is safer if users may have a
' CGA monitor with EGA or VGA card. Otherwise, this is not as attractive a cursor.
IF OvrTyp THEN CursStrt = ScnLins * .6 ELSE CursStrt = 0 'Initial call in insert mode
LinLen = RCol - LCol + 1: NumRow = ERow - SRow + 1
FOR i = SRow TO ERow 'Set input text lines into a$ for edit
a$(i) = SPACE$(LinLen)
LSET a$(i) = Txt$(i - SRow + 1)
LOCATE i, LCol, 0 'Print in block set by rows & columns
PRINT a$(i);
NEXT i
IF KeyCode = 999 THEN EXIT SUB 'Use for printing text block and returning
buffer$ = SPACE$(LinLen) 'Blank line is initial buffer for pasting
CursCol = 1: CursRow = SRow
DO 'Start edit loop
LOCATE CursRow, CursCol + LCol - 1, 1, CursStrt, ScnLins 'Edit cursor placement
CALL KeyPress(KeyCode)
SELECT CASE KeyCode
CASE 8 'Backspace
IF CursCol > 1 THEN
IF OvrTyp THEN
MID$(a$(CursRow), CursCol, 1) = " ": PRINT " ";
ELSE
MID$(a$(CursRow), CursCol - 1) = MID$(a$(CursRow), CursCol) + " "
LOCATE , CursCol + LCol - 2, 0
PRINT MID$(a$(CursRow), CursCol - 1);
END IF
CursCol = CursCol - 1
END IF
CASE 13 'Carriage Return
IF NumRow = 1 THEN EXIT DO
CursCol = 1
IF CursRow < ERow THEN
CursRow = CursRow + 1
ELSE EXIT DO
END IF
CASE 27 'Escape to Exit BlkEdit
EXIT DO
CASE 1 TO 6, 32 TO 254 'Print character within ASCII code range
LOCATE , , 0
IF OvrTyp THEN
MID$(a$(CursRow), CursCol) = CHR$(KeyCode): PRINT CHR$(KeyCode);
ELSE
MID$(a$(CursRow), CursCol) = CHR$(KeyCode) + MID$(a$(CursRow), CursCol)
PRINT MID$(a$(CursRow), CursCol);
END IF
IF CursCol < LinLen THEN CursCol = CursCol + 1
CASE -75 'Left Arrow
IF CursCol > 1 THEN CursCol = CursCol - 1
CASE -77 'Right Arrow
IF CursCol < LinLen THEN CursCol = CursCol + 1
CASE -72 'Up Arrow
IF NumRow = 1 THEN EXIT DO
IF CursRow = SRow THEN EXIT DO
CursRow = CursRow - 1
CASE -80 'Down Arrow
IF NumRow = 1 THEN EXIT DO
IF CursRow = ERow THEN EXIT DO
CursRow = CursRow + 1
CASE -71 'Home to Column 1
CursCol = 1
CASE -79 'End to Last Character +1
FOR i = LinLen TO 1 STEP -1
IF MID$(a$(CursRow), i, 1) <> " " THEN EXIT FOR
NEXT i
IF i < LinLen THEN CursCol = i + 1 ELSE CursCol = LinLen
CASE -82 'Insert Key to Toggle Overtype to Insert
OvrTyp = NOT OvrTyp 'Don't go to thin cursor for laptop readibility
IF OvrTyp THEN CursStrt = ScnLins * .6 ELSE CursStrt = 0
CASE -83 'Delete at Cursor
IF CursCol < LinLen THEN
MID$(a$(CursRow), CursCol) = MID$(a$(CursRow), CursCol + 1) + " "
ELSE MID$(a$(CursRow), CursCol) = " "
END IF
LOCATE , , 0
PRINT MID$(a$(CursRow), CursCol);
CASE -119 'Ctrl+Home to go to start of block
CursRow = SRow: CursCol = 1
CASE -117 'Ctrl+End to go to end of block
FOR i = ERow TO SRow STEP -1
IF a$(i) <> SPACE$(LinLen) THEN EXIT FOR
NEXT i
CursCol = 1
IF i < ERow THEN CursRow = i + 1 ELSE CursRow = ERow
'CASE -30, -25 'Alt+A to add a blank line at cursor or
' IF a$(ERow) = SPACE$(LinLen) THEN 'Alt+P to paste buffer
' FOR i = ERow - 1 TO CursRow STEP -1
' a$(i + 1) = a$(i)
' NEXT i
' IF KeyCode = -25 THEN
' a$(CursRow) = buffer$
' ELSE
' a$(CursRow) = SPACE$(LinLen)
' END IF
' FOR i = CursRow TO ERow
' LOCATE i, LCol, 0
' PRINT a$(i);
' NEXT i
' CursCol = 1
' ELSE 'Warn of attempt to insert line and lose bottom
' SOUND 440, 1 ' line. Requires Deleting bottom line first
' END IF
'CASE -32 'Alt+D to Delete current line
' FOR i = CursRow TO ERow - 1
' a$(i) = a$(i + 1)
' LOCATE i, LCol, 0
' PRINT a$(i);
' NEXT i
' a$(ERow) = SPACE$(LinLen)
' LOCATE ERow, LCol, 0
' PRINT a$(ERow);
' CursCol = 1
'CASE -46 'Alt+C to copy current line to buffer
' buffer$ = a$(CursRow)
CASE -73 'PageUp
IF NumRow = 1 THEN EXIT DO
IF CursRow = SRow THEN EXIT DO
CursRow = SRow
CASE -81 'PageDown
IF NumRow = 1 THEN EXIT DO
IF CursRow = ERow THEN EXIT DO
CursRow = ERow
'CASE 9 'Tab for 5 space increments from LCol
' i = 1
' DO
' i = i + 5
' LOOP WHILE i <= CursCol
' IF i <= LinLen THEN CursCol = i
'CASE -15 'Sh+Tab to backup cursor to next Tab Stop
' i = 1
' DO
' i = i + 5
' LOOP WHILE i < CursCol
' i = i - 5
' CursCol = i
CASE ELSE
EXIT DO
END SELECT
LOOP
FOR i = SRow TO ERow 'Put edited lines back in Txt$
Txt$(i - SRow + 1) = RTRIM$(a$(i))
NEXT i
LOCATE , , 0
ERASE a$
END SUB
SUB BoxDisplay (Nitm, Nstrt, Txt$(), Ctrl, SDLin, ColCod$, Shdw, SelKey) STATIC
'Displays Box centered on screen with menu or message items inside.
'Can be used as a scroll box for multi-screen menu items.
' Nitm = number of items in displayed lines.
' Nstrt = starting row for highlighted item for Ctrl=5 displays (good for window returns)
' Txt$(i) = array of displayed lines.
' Ctrl = 0,1 for <=15 centered lines; = 2,3 for left justified lines;
' (0,2 wait for key press. 1,3 display box and return)
' = 4 for selecting one item by first character or return (=Esc)
' = 5 for selecting list item via highlight bar plus Return. first letter
' match moves highlight bar to that location. This is the normal scroll box.
' SDLin = single or double line option, = 1 or 2, for box
' ColCod$ = box color codes: = w for window, = g for text, = m for menu colors
' Shdw = adds shadow to box if = 1
' SelKey = array item number selected. = 0 if <Esc> or return without selection.
'Saves current video page to page 3 based on menu system and other program sections
' using 1-2 for nested windows and switching between views.
'Requires ScrnCopy, BoxDraw, KeyPress
CALL ScrnCopy(0, 3) 'Save current video page
IF ColCod$ = "w" THEN 'Determine colors to use
FGrnd = pc.wf: BGrnd = pc.wb
ELSEIF ColCod$ = "g" THEN
FGrnd = pc.fg: BGrnd = pc.bg
ELSE
FGrnd = pc.mf: BGrnd = pc.mb
END IF
ndlins = Nitm
IF Nitm > 15 THEN ndlins = 15 '15 max lines in box
rstrt = (21 - ndlins) \ 2 'Set row positions
rend = rstrt + 3 + ndlins
LinLen = 0 'Find longest line length
FOR i = 1 TO Nitm
a = LEN(Txt$(i))
IF a > LinLen THEN LinLen = a
NEXT i
cstrt = (76 - LinLen) \ 2 'Set column positions
cend = cstrt + 3 + LinLen
CALL BoxDraw(cstrt, cend, rstrt, rend, 1, SDLin, FGrnd, BGrnd, Shdw) 'Draw box
rstrt = rstrt + 1: rmsgt = 1 'Prepare for inside text
IF Ctrl < 5 THEN 'Print messages here
IF Ctrl < 2 THEN 'Centered message
FOR i = 1 TO ndlins
CALL CenterLin(rstrt + i, cstrt + 2, cend - 2, Txt$(i))
NEXT i
IF Ctrl = 1 THEN EXIT SUB
ELSE
FOR i = 1 TO ndlins 'Left-justified message
LOCATE rstrt + i, cstrt + 2
PRINT Txt$(i);
NEXT i
IF Ctrl = 3 THEN EXIT SUB
END IF
CALL KeyPress(SelKey)
IF SelKey > 47 AND SelKey < 123 THEN 'Could be Alpha-Num keypress
IF Ctrl = 4 THEN 'If select option, then search for match
t$ = UCASE$(CHR$(SelKey))
FOR i = 1 TO Nitm
IF UCASE$(MID$(Txt$(i), 1, 1)) = t$ THEN
SelKey = i: CALL ScrnCopy(3, 0)
EXIT SUB
END IF
NEXT i
END IF
END IF
SelKey = 0: CALL ScrnCopy(3, 0)
EXIT SUB 'No match or <Esc>
END IF
cstrt = cstrt + 1 'Prepare for menu items for Ctrl=5
ract = Nstrt: lin$ = SPACE$(LinLen)
MsgStrt:
FOR i = 1 TO ndlins 'Print menu items
LOCATE rstrt + i, cstrt
IF (rmsgt + i - 1) <= Nitm THEN
LSET lin$ = Txt$(rmsgt + i - 1)
IF i = ract THEN 'Reverse colors on highlight row
COLOR BGrnd, FGrnd
PRINT " "; lin$; " ";
COLOR FGrnd, BGrnd
ELSE
PRINT " "; lin$; " ";
END IF
ELSE
PRINT SPACE$(LinLen + 2) 'If not enough items to fill box, then
END IF 'print blank lines
NEXT i
CALL KeyPress(KeyCode) 'Get keypress for action
SELECT CASE KeyCode
CASE IS = 27 'Esc
SelKey = 0
CALL ScrnCopy(3, 0)
EXIT SUB
CASE IS = 13 'Return with highlight item
SelKey = rmsgt + ract - 1
CALL ScrnCopy(3, 0)
EXIT SUB
CASE 65 TO 90, 97 TO 122 'Locate first occurrence of keypress
t$ = UCASE$(CHR$(KeyCode)) ' letter and make it the highlighted item
FOR i = 1 TO Nitm
IF UCASE$(MID$(Txt$(i), 1, 1)) = t$ THEN
IF (i < rmsgt + ndlins) AND (i >= rmsgt) THEN
ract = i - rmsgt + 1
ELSE
rmsgt = i: ract = 1
END IF
GOTO MsgStrt:
END IF
NEXT i
CASE IS = -71, -35 'Home, Alt-H - go to first item
rmsgt = 1: ract = 1
CASE IS = -79, -18 'End, Alt-E - go to last item
ndlast = Nitm - (Nitm \ ndlins) * ndlins
IF ndlast = 0 THEN
ract = ndlins
rmsgt = Nitm - ndlins + 1
ELSE
ract = ndlast: rmsgt = Nitm - ndlast + 1
END IF
CASE IS = -73, -22 'PgUp, Alt-U - go to top of window, then
IF ract = 1 THEN 'scroll to next block of lines
rmsgt = rmsgt - ndlins
IF rmsgt < 1 THEN rmsgt = 1
ELSE
ract = 1
END IF
CASE IS = -81, -32 'PgDn, Alt-D - go to btm of window, then
IF rmsgt + ndlins - 1 >= Nitm THEN 'scroll to next block of lines
ract = Nitm - rmsgt + 1 'Check for last screen
ELSE
IF ract < ndlins THEN
ract = ndlins
ELSE
rmsgt = rmsgt + ndlins
ract = 1
END IF
END IF
CASE IS = -72 'Up Arrow
IF ract > 1 THEN
ract = ract - 1
ELSE
IF rmsgt > 1 THEN rmsgt = rmsgt - 1
END IF
CASE IS = -80, 32 'Down Arrow, space
IF rmsgt + ndlins - 1 >= Nitm THEN
IF ract < Nitm - rmsgt + 1 THEN ract = ract + 1
ELSE
IF ract = ndlins THEN
rmsgt = rmsgt + 1
ELSE
ract = ract + 1
END IF
END IF
CASE ELSE
END SELECT
GOTO MsgStrt:
END SUB
SUB BoxDraw (LCol, RCol, SRow, ERow, BFil, Brdr, FGrnd, BGrnd, Shdw) STATIC
'Draws a Box for use of on screen windows in program.
'Plain box or optional single or double line border box with optional shadow.
' LCol = starting left column of box
' RCol = ending right column
' SRow = starting row of box
' ERow = ending row
' BFil = if =1 then fills in box with background color
' Brdr = if =1/2 then uses single/double line border for box
' FGrnd = box foreground color
' BGrnd = box background color. will use color 0 for box shadow.
' Shdw = shadow option if =1
COLOR FGrnd, BGrnd 'Set box window colors
IF BFil = 1 THEN 'Fill in box with blank spaces
FOR i = SRow TO ERow
LOCATE i, LCol, 0
PRINT SPACE$(RCol - LCol + 1);
NEXT i
END IF
IF Brdr = 0 THEN EXIT SUB 'If no border then exit
IF Brdr = 1 THEN 'Set ASCII code border characters
c1 = 196: c2 = 179: c3 = 218: c4 = 191: c5 = 192: c6 = 217
ELSE
c1 = 205: c2 = 186: c3 = 201: c4 = 187: c5 = 200: c6 = 188
END IF
LOCATE SRow, LCol + 1 'Print top and bottom borders
PRINT STRING$(RCol - LCol - 1, c1);
LOCATE ERow, LCol + 1
PRINT STRING$(RCol - LCol - 1, c1);
LOCATE ERow + 1, LCol + 2
IF Shdw = 1 THEN 'Print bottom shadow
COLOR 0: PRINT STRING$(RCol - LCol + 1, 219); : COLOR FGrnd, BGrnd
END IF
FOR i = SRow + 1 TO ERow - 1 'Print side borders
LOCATE i, LCol
PRINT CHR$(c2);
LOCATE i, RCol
PRINT CHR$(c2);
IF Shdw = 1 THEN '+ Right-side shadow
COLOR 0: PRINT STRING$(2, 219); : COLOR FGrnd
END IF
NEXT i
LOCATE SRow, LCol: PRINT CHR$(c3); 'Print corner lines
LOCATE SRow, RCol: PRINT CHR$(c4);
LOCATE ERow, LCol: PRINT CHR$(c5);
LOCATE ERow, RCol: PRINT CHR$(c6);
IF Shdw = 1 THEN '+ Lower-right shadow
COLOR 0: PRINT STRING$(2, 219); : COLOR FGrnd
END IF
END SUB
SUB CenterLin (Row, LCol, RCol, Text$) STATIC
'Centers a line of Text on Row within L and R Columns
' Row = Row for printing line
' L,RCol = Starting left and ending right column for centering
' Text$ = String of text to center
dlen = (RCol - LCol - LEN(Text$) + 1) \ 2
IF dlen < 0 THEN EXIT SUB
LOCATE Row, LCol + dlen
PRINT Text$;
END SUB
SUB DialogBox (Ddflts$, Dsin$, Dsout$, KeyCode, DBCode) STATIC
'Displays dialog box in response to Alt-Key Menu item selection.
'Is independent of the AKMnu system and called by MainCalc in response to a
' particular menu system selection.
'In general it sets up a list of fixed categories on the left and allows the
' user to select or edit a list of items positioned at the right of each category.
'Use cursor movement keys to get highlite bar to desired category.
'<CR> then lets you modify item for that category. <CR> returns to the dialog
' box categories. <Esc> returns to pull-down menu system with selected items.
'DATA statements building the menu are the following:
' - Dialog Box Title (optional), number of following data statements ("ncat")
' - "ncat" data statements describing categories for dialog
' - Optional default starting list of all dialog items
'The different categories of dialog input are the following:
' 1 - text input by user into a defined field. Uses BlkEdit for the field editor.
' 2 - select a single item from a vertical box menu. Uses BoxDisplay.
' 3 - displays options for a category. One option is selected by moving a "*"
' character with the cursor keys.
' 4 - a category is toggled for select or not as noted by a check character.
' 5 - a row of boxed "control buttons". Only one row permitted. <CR> on these
' exits the routine to allow user adjustment of input items and optional
' return to the routine.
' 6 - a line of explanatory text that cannot be selected. Can be blank and used
' as a spacer to better display related categories. Top and bottom categories
' can be number 6's. No more than one 6 can be used in adjacent positions.
' 7 - an optional string containing the default or startup list of items. Is not
' a displayed category.
'The format of the category data statements are as follows. 0 means not selected and 1
' or 1 thru n for multiple items means that item is selected.
' 1 - type, hilite key letter, category name, field length for editing.
' 2 - type, hilite key letter, category name, no. of selectable items, list of
' items with "/" separator
' 3 - (same as 2)
' 4 - type, hilite key letter, category name
' 5 - type, hilite key string, no. of control buttons, list of controls with
' "/" separator
' 6 - type, string (including blank)
' 7 - type, string containing initial category selections with "/" separator. Include
' entries for all 1-5 category items. (Start cat 5 with "0")
'Routine I/O is the following:
' Ddflts$ - optional default string of items.
' Dsin$ - input list of selected items
' (For both of these variables, the calling routine must control the format, especially the
' length of any category 1 input string. BlkEdit will limit length, but longer items can be printed.)
' Dsout$ - list of selected items upon exit from routine
' KeyCode - 0 for <Esc> or 1-n for 1-n control button selection
' DBCode - operating direction code. initial call to routine with 1 to
' read and build dialog box. Return after category 5 exit with DBCode=2.
' Although somewhat complicated, this allows great flexibility in controlling
' allowable input in your program. Program and user defaults can be used.
'Requires KeyPress, BlkEdit, BoxDisplay, CenterLin, pc.(PgmColors) using menu and background colors.
Dsout$ = Dsin$: Dtmp$ = Dsin$ 'Store input item string
IF DBCode = 2 THEN GOTO DBoxLoop1: 'If returning from ctrl button exit, resume
CALL ScrnCopy(0, 1) 'Save current screen
READ title$, ncat 'Read dialog box description
REDIM hlk$(1 TO ncat), cat(1 TO ncat, 1 TO 5), drow$(1 TO ncat, 1 TO 3)
' cat (1 to 5) are: type, cat len, item max len, no. items, strt row offset
' drow$ (1 to 3) are: cat, items, selected item
lcat = 0: litm = 0: llins = 0: lmax = 0 'Find max length of category, items, total width
FOR i = 1 TO ncat
READ cat(i, 1) 'Category of dialog item
SELECT CASE cat(i, 1)
CASE IS = 1 'Input field type
llins = llins + 1: cat(i, 5) = llins
READ hlk$(i), drow$(i, 1), cat(i, 3) 'Highlite key, Name and input length
cat(i, 2) = LEN(drow$(i, 1)) 'Length of name
IF cat(i, 2) > lcat THEN lcat = cat(i, 2) 'Find longest lengths
IF cat(i, 3) > litm THEN litm = cat(i, 3)
CASE IS = 2, 3 'Menu or (*) list item
READ hlk$(i), drow$(i, 1), cat(i, 4), drow$(i, 2) 'Hilite key, category, no of items, itm list (/separator)
cat(i, 2) = LEN(drow$(i, 1))
IF cat(i, 2) > lcat THEN lcat = cat(i, 2)
cat(i, 3) = 0: istrt = 0
FOR k = 1 TO LEN(drow$(i, 2)) 'Find length of longest menu item
IF MID$(drow$(i, 2), k, 1) = "/" THEN
IF istrt > cat(i, 3) THEN cat(i, 3) = istrt
istrt = 0
ELSE
istrt = istrt + 1
END IF
NEXT k
IF istrt > cat(i, 3) THEN cat(i, 3) = istrt 'Store longest length item
IF cat(i, 1) = 2 THEN 'Determine row position
IF cat(i, 3) > litm THEN litm = cat(i, 3)
llins = llins + 1: cat(i, 5) = llins
ELSE
IF cat(i, 3) + 4 > litm THEN litm = cat(i, 3) + 4 'Allow for * select item
cat(i, 5) = llins + 1
llins = llins + cat(i, 4)
END IF
CASE IS = 4 'Checked option
llins = llins + 1: cat(i, 5) = llins
READ hlk$(i), drow$(i, 1)
cat(i, 2) = LEN(drow$(i, 1))
IF cat(i, 2) > lcat THEN lcat = cat(i, 2)
IF litm < 1 THEN litm = 1
CASE IS = 5 'Single set of control buttons allowed
cat(i, 5) = llins + 2
llins = llins + 3
READ hlk$(i), cat(i, 4), drow$(i, 1) 'No of items, list (/ separator)
cat(i, 2) = LEN(drow$(i, 1)) + (cat(i, 4) - 1) * 3 + 2
IF cat(i, 2) > lmax THEN lmax = cat(i, 2)
REDIM itm5$(1 TO cat(i, 4)), col5(1 TO cat(i, 4), 1 TO 2), hlk5$(1 TO cat(i, 4))
k = 1
FOR j = 1 TO LEN(drow$(i, 1))
a$ = MID$(drow$(i, 1), j, 1)
IF a$ = "/" THEN
k = k + 1
ELSE
itm5$(k) = itm5$(k) + a$
END IF
NEXT j
FOR j = 1 TO cat(i, 4)
hlk5$(j) = MID$(hlk$(i), j, 1)
col5(j, 2) = LEN(itm5$(j))
NEXT j
CASE IS = 6 'User defined string. Typically
llins = llins + 1 ' separator bar or subheading
cat(i, 5) = llins
READ drow$(i, 1)
cat(i, 2) = LEN(drow$(i, 1))
IF cat(i, 2) > lmax THEN lmax = cat(i, 2)
CASE IS = 7 'Startup default string
READ Ddflts$
ncat = ncat - 1 'Retain only categories for print rows
END SELECT
NEXT i
IF Dsin$ = "" THEN 'If no Dsin$ on initial call, assume
Dsin$ = Ddflts$: Dsout$ = Ddflts$: Dtmp$ = Ddflts$ 'default is provided
END IF
rstrt = (21 - llins) \ 2 'Set up box positions
rend = rstrt + llins + 1
lmax = lmax + 2
IF lcat + litm + 4 > lmax THEN lmax = lcat + litm + 4 'Be sure wide enough
cstrt = (78 - lmax) \ 2 'Start, end columns
cend = cstrt + lmax + 2
CALL BoxDraw(cstrt, cend, rstrt, rend, 1, 1, pc.mf, pc.mb, 1) 'Draw dialog box in menu colors
IF title$ > " " THEN CALL CenterLin(rstrt, cstrt, cend, title$) 'Put title in box top bar
cstrt = cstrt + 2: cistrt = cstrt + lcat + 2 'Category and item starting columns
FOR i = 1 TO ncat 'Calc locations and print categories
SELECT CASE cat(i, 1)
CASE 1 TO 4, 6 'Categories 1-4 and 6
LOCATE rstrt + cat(i, 5), cstrt
FOR j = 1 TO cat(i, 2)
a$ = MID$(drow$(i, 1), j, 1)
IF hlk$(i) = a$ THEN 'If at hilite key position, print letter
COLOR pc.hk
PRINT hlk$(i);
COLOR pc.mf
ELSE
PRINT a$; 'Print normal category letter
END IF
NEXT j
IF cat(i, 1) = 3 THEN 'For category 3, display selectable items
il = 0
FOR j = 1 TO cat(i, 4)
i$ = ""
DO
il = il + 1
a$ = MID$(drow$(i, 2), il, 1)
IF a$ = "/" THEN
EXIT DO
ELSE
i$ = i$ + a$
END IF
LOOP UNTIL LEN(drow$(i, 2)) = il
LOCATE rstrt + cat(i, 5) + j - 1, cistrt
PRINT i$;
NEXT j
END IF
CASE IS = 5 'Control buttons are special
lspc = (lmax - cat(i, 2)) \ 2 'Max length of ctrl btm line
col5(1, 1) = cstrt + lspc + 1
FOR j = 2 TO cat(i, 4)
col5(j, 1) = col5(j - 1, 1) + col5(j - 1, 2) + 4
NEXT j
rs = rstrt + cat(i, 5) - 1: re = rs + 2
FOR j = 1 TO cat(i, 4) 'Put boxes around text
cs = col5(j, 1) - 1: ce = cs + col5(j, 2) + 1
CALL BoxDraw(cs, ce, rs, re, 0, 1, pc.mf, pc.mb, 0)
LOCATE rs + 1, col5(j, 1)
FOR k = 1 TO col5(j, 2)
a$ = MID$(itm5$(j), k, 1)
IF hlk5$(j) = a$ THEN 'Each button can have a hilite key
COLOR pc.hk
PRINT hlk5$(j);
COLOR pc.mf
ELSE
PRINT a$;
END IF
NEXT k
NEXT j
CASE ELSE
END SELECT
NEXT i
CALL ScrnCopy(0, 2) 'Save the dialog box screen with categories
cstrt = cstrt - 1
IF cat(1, 1) > 5 THEN ract = 2 ELSE ract = 1 'Set starting point. ract is active row
c5itm = 1 'Initially go to first control button
lini$ = SPACE$(litm) 'Item input variable
DBoxLoop1: 'Return point for ctrl button action
GOSUB DStrItm: 'Put string into items in case it changed
DBoxLoop2: 'Loop for printing items after each category
CALL ScrnCopy(2, 0) 'Recall the box
COLOR pc.bg, pc.mb
FOR i = 1 TO ncat 'Loop thru the categories and print
LOCATE rstrt + cat(i, 5)
SELECT CASE cat(i, 1)
CASE IS = 1, 2
LOCATE , cistrt
LSET lini$ = drow$(i, 3)
PRINT lini$; 'Print input string in field
CASE IS = 3
FOR j = 1 TO cat(i, 4)
LOCATE rstrt + cat(i, 5) + j - 1, cistrt + cat(i, 3) + 2
IF j = VAL(drow$(i, 3)) THEN
i$ = "*"
ELSE
i$ = " "
END IF
PRINT "("; i$; ")"; 'Print empty or selected item
NEXT j
CASE IS = 4
IF drow$(i, 3) = "1" THEN 'If selected (=1) then print
LOCATE , cistrt
PRINT CHR$(251); 'Use divider character as "check"
END IF
CASE ELSE
END SELECT
NEXT i
CALL ScrnCopy(0, 3) 'Save complete dialog box without hilite bar
DBoxLoop3: 'Primary loop for displaying hilite bar
CALL ScrnCopy(3, 0)
COLOR pc.mb, pc.mf
IF cat(ract, 1) = 5 THEN 'Special treatment of control buttons
LOCATE rstrt + cat(ract, 5), col5(c5itm, 1)
PRINT itm5$(c5itm);
a$ = MID$(hlk$(ract), c5itm, 1)
b = INSTR(itm5$(c5itm), a$)
IF b > 0 THEN
LOCATE , col5(c5itm, 1) + b - 1
COLOR pc.hk
PRINT a$;
COLOR pc.mf
END IF
ELSE 'Display hilite bar for other categories
LOCATE rstrt + cat(ract, 5), cstrt
PRINT " "; drow$(ract, 1); TAB(cistrt - 1);
b = INSTR(drow$(ract, 1), hlk$(ract))
IF b > 0 THEN
LOCATE , cstrt + b
COLOR pc.hk
PRINT hlk$(ract);
COLOR pc.mf
END IF
END IF
DBoxLoop4: 'Loop for moving hilite bar and selecting categories
CALL KeyPress(KeyCode)
SELECT CASE KeyCode
CASE IS = 27 'Update and escape
KeyCode = 0
c5itm = 0 'Not an exit with a control button
GOSUB DItmStr: 'Store selected items in string
GOTO DBExit:
CASE IS = 13 'Alter or select this item
CALL ScrnCopy(3, 0) 'Makes category highlite go away during item edit
GOTO DBoxLoop5:
CASE 65 TO 90, 97 TO 122, 48 TO 57 'Letters and numbers
t$ = UCASE$(CHR$(KeyCode))
FOR i = 1 TO ncat
IF cat(i, 1) = 5 THEN
c5itm = INSTR(UCASE$(hlk$(i)), t$)
IF c5itm > 0 THEN
ract = i
GOTO DBoxLoop3:
END IF
c5itm = 1
ELSE
IF UCASE$(hlk$(i)) = t$ THEN
ract = i
GOTO DBoxLoop3:
END IF
END IF
NEXT i
CASE IS = -72, -22 '<Up>,Alt-U
IF ract > 1 THEN
ract = ract - 1
IF cat(ract, 1) > 5 THEN
IF ract > 1 THEN ract = ract - 1 ELSE ract = ract + 1
END IF
GOTO DBoxLoop3:
END IF
CASE IS = -80, -32, 32 '<Down>,Alt-D,<Space>
IF ract < ncat THEN
ract = ract + 1
IF cat(ract, 1) = 6 THEN
IF ract < ncat THEN ract = ract + 1 ELSE ract = ract - 1
END IF
GOTO DBoxLoop3:
END IF
CASE IS = -73, -71, -35 '<PgUp>,Home,Alt-H
IF cat(1, 1) = 6 THEN ract = 2 ELSE ract = 1
GOTO DBoxLoop3:
CASE IS = -81, -79, -18 '<PgDn>,End,Alt-E
IF cat(ncat, 1) = 6 THEN ract = ncat - 1 ELSE ract = ncat
GOTO DBoxLoop3:
CASE IS = -75, -38 '<Left>,Alt-L
IF cat(ract, 1) = 5 THEN
IF c5itm = 1 THEN
c5itm = cat(ract, 4)
ELSE
c5itm = c5itm - 1
END IF
END IF
GOTO DBoxLoop3:
CASE IS = -77, -19 '<Right>,Alt-R
IF cat(ract, 1) = 5 THEN
IF c5itm = cat(ract, 4) THEN
c5itm = 1
ELSE
c5itm = c5itm + 1
END IF
END IF
GOTO DBoxLoop3:
CASE ELSE 'Allow for any other keypress
END SELECT
GOTO DBoxLoop4:
DBoxLoop5: 'Section for updating items
COLOR pc.mb, pc.mf
SELECT CASE cat(ract, 1)
CASE IS = 1
REDIM itm$(1 TO 1)
itm$(1) = drow$(ract, 3) 'Allow user to edit field via itm$
CALL BlkEdit(itm$(), cistrt, cistrt + cat(ract, 3) - 1, rstrt + cat(ract, 5), rstrt + cat(ract, 5), KeyCode)
drow$(ract, 3) = itm$(1)
CASE IS = 2
REDIM itm$(1 TO cat(ract, 4)) 'Set up selectable items in array
k = 0: l = 1
FOR i = 1 TO cat(ract, 4) 'Extract from /-separated list
itm$(i) = ""
FOR j = l TO LEN(drow$(ract, 2))
a$ = MID$(drow$(ract, 2), j, 1)
IF a$ = "/" THEN EXIT FOR
itm$(i) = itm$(i) + a$
NEXT j
l = j + 1
IF itm$(i) = drow$(ract, 3) THEN k = i
NEXT i
IF k < 1 THEN k = 1 'Display as new menu using window colors
CALL BoxDisplay(cat(ract, 4), k, itm$(), 5, 2, "w", 1, SelKey)
IF SelKey < 1 THEN SelKey = k 'If <Esc> retain first item
drow$(ract, 3) = itm$(SelKey)
CASE IS = 3
ri = rstrt + cat(ract, 5) - 1 'Set up variables to move "*" around
ci = cistrt + cat(ract, 3) + 2
ni = VAL(drow$(ract, 3))
DO
FOR i = 1 TO cat(ract, 4) 'Print blank or character
LOCATE ri + i, ci
IF i = ni THEN PRINT "(*)"; ELSE PRINT "( )";
NEXT i
CALL KeyPress(KeyCode)
SELECT CASE KeyCode
CASE IS = 27, 13, -75, -38, -77, -19 'Go back to category
drow$(ract, 3) = STR$(ni)
EXIT DO
CASE IS = -72, -22 'Up movement
IF ni > 1 THEN ni = ni - 1 ELSE ni = cat(ract, 4)
CASE IS = -80, -32, 32 'Down movement
IF ni < cat(ract, 4) THEN ni = ni + 1 ELSE ni = 1
CASE IS = -73, -71, -35 'First item
ni = 1
CASE IS = -81, -79, -18 'Last item
ni = cat(ract, 4)
CASE 49 TO 57 'Can select by number
ni = KeyCode - 48
IF ni > cat(ract, 4) THEN ni = cat(ract, 4)
CASE ELSE 'Allow for user errors
END SELECT
LOOP
CASE IS = 4
LOCATE rstrt + cat(ract, 5), cistrt
IF drow$(ract, 3) = "1" THEN 'Toggle selection
drow$(ract, 3) = "0"
PRINT " ";
ELSE
drow$(ract, 3) = "1"
PRINT CHR$(251);
END IF
CASE IS = 5
GOSUB DItmStr: 'Store current items in string
KeyCode = c5itm 'Note which button was <CR>'d
EXIT SUB
CASE ELSE
END SELECT
GOTO DBoxLoop2: 'Loop to box item print
DBExit:
CALL ScrnCopy(1, 0) 'Restore screen and erase arrays
ERASE hlk$, cat, drow$, itm5$, col5, hlk5$, itm$
title$ = "": Dtmp$ = ""
EXIT SUB
DStrItm: 'Put selection string (dtmp$) into individual item variables
il = 0
FOR i = 1 TO ncat
IF cat(i, 1) < 6 THEN
drow$(i, 3) = ""
DO
il = il + 1
a$ = MID$(Dtmp$, il, 1)
IF a$ = "/" THEN
EXIT DO
ELSE
drow$(i, 3) = drow$(i, 3) + a$
END IF
LOOP UNTIL LEN(Dsin$) = il
END IF
NEXT i
RETURN
DItmStr: 'Store individual items in dsout$ string
Dsout$ = ""
FOR i = 1 TO ncat
SELECT CASE cat(i, 1)
CASE 1 TO 4
Dsout$ = Dsout$ + drow$(i, 3) + "/"
CASE IS = 5
Dsout$ = Dsout$ + STR$(c5itm) + "/"
CASE ELSE
END SELECT
NEXT i
Dsout$ = LEFT$(Dsout$, LEN(Dsout$) - 1)
RETURN
END SUB
SUB KeyPress (KeyCode) STATIC
'Processes next keypress in buffer.
'Returns negative of second code for extended codes.
DO
ky$ = INKEY$
LOOP UNTIL LEN(ky$)
IF LEN(ky$) = 1 THEN
KeyCode = ASC(ky$)
ELSE
KeyCode = -ASC(RIGHT$(ky$, 1))
END IF
END SUB
SUB MainCalc STATIC
'Dummy main part of program containing menu system
'Key items to note are the integer control codes to convert menu items to program
' actions and the use of SELECT CASE.
'Note that with another set of DATA statements, your program could have two menu systems;
' e.g. MainMenu1 and MainMenu2.
'If you extend to highly nested menu systems and scroll boxes, beware of running out of
' video pages.
REDIM MnuCtrl(1 TO 1), MnuItm1$(1 TO 1), MnuItm2$(1 TO 1, 1 TO 1) 'For AKMnuRead call
DIM z$(1 TO 50), y$(1 TO 6) 'Set up some strings for menu items
FOR i = 1 TO 50
n = 20 * RND(1)
z$(i) = ""
FOR j = 1 TO n
z$(i) = z$(i) + CHR$(65 + 25 * RND(1))
NEXT j
NEXT i
REDIM a$(1 TO 5) 'Set up a block edit field
a$(1) = "This is a block of text you can edit."
a$(2) = "Exiting from block with typical keys will go"
a$(3) = "to a selection box. Alt-keys activate menus."
RESTORE MainMenu1: 'Read menu parameters
CALL AKMnuRead(MnuCtrl(), MnuItm1$(), MnuItm2$())
COLOR pc.fg, pc.bg 'Prepare for screens
WIDTH 80, 25
CLS
'Let's have a heading
Text$ = "DEMO PROGRAM FOR WINDOW - MENU SYSTEM"
COLOR pc.bt
CALL CenterLin(1, 1, 80, Text$) 'Put title in center at top
COLOR pc.fg
Text$ = " This is Dummy Message Line at Bottom of Screen" 'Reserve last line for pgm comments/help
CALL StrngBar(25, Text$)
CALL AKMnuSet(MnuCtrl(), MnuItm1$(), MnuItm2$()) 'Display horizontal menu bar
FOR i = 4 TO 23 'Put some stuff on the screen
FOR j = 3 TO 78
LOCATE i, j, 0
PRINT CHR$(33 + 90 * RND(1));
NEXT j
NEXT i
CALL BoxDraw(10, 70, 10, 16, 1, 1, pc.fg, pc.bg, 0) 'Set up box for block edit
Dsin1$ = "c:\qbasic\*.*/WK2/2/0/1/1/0" 'Set up initial items for dialog box (could be cal'd by pgm)
AKStart: 'Program screen operations
COLOR pc.fg, pc.bg
CALL BlkEdit(a$(), 12, 68, 11, 15, KeyCode) 'Start by editing block of text
SELECT CASE KeyCode 'Exited block. Branch based on return KeyCode
CASE IS = 13 'Example action following block edit by <CR>
y$(1) = "Add a new item to list"
y$(2) = "Delete the current item"
y$(3) = "Modify the current item"
y$(4) = "Reconfigure the support plan"
y$(5) = ""
y$(6) = " (Select by First Letter)"
CALL BoxDisplay(6, 1, y$(), 4, 2, "w", 1, SelKey)
IF SelKey > 0 AND SelKey < 5 THEN
y$(2) = y$(SelKey)
y$(1) = "You selected the following program branch ..."
y$(3) = "< Press Any Key To Continue >"
CALL BoxDisplay(3, 1, y$(), 0, 2, "w", 1, SelKey)
END IF
GOTO AKStart:
CASE IS = 27 '<Esc>. Let's go home
EXIT SUB
CASE -50 TO -44, -38 TO -30, -25 TO -16, -68 'Alt-alpha, + F10 key traps to go to menu
MMenu1Strt:
CALL AKMnuCtrl(KeyCode, MnuCtrl(), MnuItm1$(), MnuItm2$(), SelKey)
CASE ELSE 'Would direct to different pgm options
y$(1) = "Main Program Trapped KeyPress = " + STR$(KeyCode)
y$(2) = "Press <Esc> in Main Program to End"
y$(3) = "< Press Any Key To Continue >"
CALL BoxDisplay(3, 1, y$(), 0, 2, "w", 1, SelKey)
GOTO AKStart:
END SELECT
Branch = 100 * KeyCode + SelKey 'Translate menu category and item into an
SELECT CASE Branch 'integer for directing program flow
CASE IS = 307 'File-Options menu item to demo dialog box
RESTORE MainDialog1: 'Goto correct DATA statements
DBCode = 1 'Initial entry code for routine
MDBoxRtn:
CALL DialogBox(dummy$, Dsin1$, Dsout1$, KeyCode, DBCode)
DBCode = 2 'Permits reentry to routine
IF KeyCode = 1 THEN Dsin1$ = Dsout1$ '"Update" selection
IF KeyCode = 2 THEN Dsin1$ = dummy$ '"Default" selection
IF KeyCode = 1 OR KeyCode = 2 THEN GOTO MDBoxRtn:
CALL ScrnCopy(1, 0) 'Return to pull-down menu screen
KeyCode = -47: GOTO MMenu1Strt:
CASE IS = 504 'Second example dialog box
RESTORE MainDialog2:
Dsin2$ = "2400/1/2/2/TTY/0"
DBCode = 1
CALL DialogBox(dummy$, Dsin2$, Dsout2$, KeyCode, DBCode)
DBCode = 2
CALL ScrnCopy(1, 0)
IF KeyCode = 1 THEN 'If returned with Connect selection, then "run"
a$(1) = ""
a$(2) = "Your Modem is Dialing ..."
a$(3) = " (Just Pretending)"
GOTO AKStart:
END IF
KeyCode = -73: GOTO MMenu1Strt: 'If returned with <Esc>, then go back to menu
CASE 1 TO 999 'Other menu branches
y$(1) = "Perform Action or Go To Program Branch --> " + STR$(Branch)
y$(2) = "Next key press will go to a simulated menu selection process"
CALL BoxDisplay(2, 1, y$(), 2, 2, "w", 1, SelKey)
CALL BoxDisplay(50, 1, z$(), 5, 2, "w", 1, SelKey) 'Select a menu item
IF SelKey = 0 THEN SelKey = 1 'In case no item selected for following display
y$(1) = "Menu item selected and used is --> " + z$(SelKey)
y$(2) = "Program might branch here or use the selected item as input to a field."
CALL BoxDisplay(2, 1, y$(), 0, 2, "w", 1, SelKey)
CASE ELSE '<Esc> from menu or other abort key
y$(1) = "This is <Esc> or Other Code Displayed for Demo Only"
y$(2) = "KeyCode = " + STR$(KeyCode) + " ; SelKey = " + STR$(SelKey)
t1 = pc.wf: t2 = pc.wb: pc.wf = 0: pc.wb = 4
CALL BoxDisplay(2, 1, y$(), 0, 2, "w", 1, SelKey) 'Manually change to red for
pc.wf = t1: pc.wb = t2 ' error or warning
END SELECT
GOTO AKStart: 'Loop until <Esc>
END SUB
SUB ScrnCopy (Src, Dst) STATIC
'Copies to/from screen pages.
'Will handle CGA - VGA using PCOPY
'Monochrome (MDA) will manually poke into host video memory
'Without assembly block memory move, will be slow for XT operation.
' OK for faster machines.
'Uses SystmData variable sdata.vid to determine adapter in use.
'Src = source page. Dst = destination page.
IF Sdata.vid = 0 THEN
DEF SEG = &HB000
t1 = 4096 * Src: t2 = 4096 * Dst
FOR i = 0 TO 3999
POKE (t2 + i), PEEK(t1 + i)
NEXT i
DEF SEG
ELSE
PCOPY Src, Dst
END IF
END SUB
SUB SetUpPgm STATIC
'Dummy setup routine for program. Would normally parse command line for
' B/W monitor option and determine video adapter from the equipment list found
' in memory. These then determine the value for Sdata.vid.
'Be sure Sdata.vid matches with your computer display mode.
'SUPPRT.ZIP found in the CIS MS Basic Library contains module SUPPRT1.BAS. This
' module provides QB routines for determining your system hardware and reading
' the command line.
'Note: You can allow your program users to set Sdata.vid numbers by displaying combos
' of foreground and background colors for selection. Don't be surprised what colors
' some people pick, so try not to restrict them.
'The following provides some examples based on the recommended use of an Sdata.vid
' integer code.
Sdata.vid = 3 ' <====== User Set Variable in This Program ****
SELECT CASE Sdata.vid
CASE IS = 0 'Monochrome MDA or Herc
pc.fg = 7: pc.bg = 0: pc.bt = 15: pc.wf = 7: pc.wb = 0
pc.mf = 0: pc.mb = 7: pc.hk = 15
CASE IS = -1, -2, -3 'CGA, EGA, VGA Mono (OK for MDA)
pc.fg = 7: pc.bg = 0: pc.bt = 15: pc.wf = 0: pc.wb = 7
pc.mf = 0: pc.mb = 7: pc.hk = 15
CASE IS = 1, 2, 3 'CGA, EGA, VGA Color. Can separate 1-3 as desired.
'PALETTE 1, 24 'Blue-Gray Optional VGA/EGA text/window backgrounds
'PALETTE 1, 16 'Dark Green vs Base Case default colors. Can use 32, 48 also
'PALETTE 1, 8 'Dark Blue/Black (every 8).
'PALETTE 1, 40 'Dark Purple/Black
'PALETTE 1, 56 'Gray
pc.fg = 7: pc.bg = 1: pc.bt = 14: pc.wf = 0: pc.wb = 7 'Base Case - W
pc.mf = 0: pc.mb = 7: pc.hk = 4 '(color white text)
'pc.fg = 0: pc.bg = 15: pc.bt = 1: pc.wf = 7: pc.wb = 1 'Base Case - B
'pc.mf = 0: pc.mb = 3: pc.hk = 15 '(color black text)
'PALETTE 6, 56: PALETTE 1, 8 'VGA Option 1 - B
'pc.fg = 0: pc.bg = 6: pc.bt = 1: pc.wf = 7: pc.wb = 1
'pc.mf = 1: pc.mb = 7: pc.hk = 15
'PALETTE 6, 56: PALETTE 1, 8 'VGA Option 2 - W
'pc.fg = 7: pc.bg = 6: pc.bt = 1: pc.wf = 1: pc.wb = 7
'pc.mf = 0: pc.mb = 7: pc.hk = 15
END SELECT
END SUB
SUB StrngBar (Row, Text$) STATIC
'String Bar generator for single row menus or text.
'Can display message related to user action or other I/O.
'Print text in menu .mf color on Row with .mb background color across Row.
' Note: By modifying AKMnuRead DATA input and AKMnuCtrl to call on a sequence
' of strings, you can display a help descriptor at the bottom of the screen
' for each menu item using StrngBar.
COLOR pc.mf, pc.mb
LOCATE Row, 1, 0
PRINT Text$; TAB(80); " ";
COLOR pc.fg, pc.bg
END SUB