home *** CD-ROM | disk | FTP | other *** search
- ;; -------------------------------------------------------------------------
- ;;
- ;; UserMenu.Scr -- Copyright (c) 1992, Oberon Software, Mankato Mn
- ;; Author: Brady Flowers, 07/09/92
- ;;
- ;; Usage: This script allows the creation of a popup menu with up to
- ;; ten items. The user may use the up and down arrows and ENTER
- ;; key to select items or may press the letter or number corresponding
- ;; to the first character of an item (these must be unique for this
- ;; to work as expected). If the user presses ESCape the menu is
- ;; aborted.
- ;;
- ;; The calling script must define at least a subset of this file's
- ;; global variables identically to the way they are defined herein.
- ;; These variables are used for input and output parameters.
- ;;
- ;; The following variables should be set on entry:
- ;; usrmnuItems -- total number of menu items (1 .. 10)
- ;; usrmnuSelect -- initially selected item (1 .. usrmnuItems)
- ;; if this is invalid, 1 is assumed
- ;; usrmnuTop -- top row of menu dialog
- ;; usrmnuLeft -- left column of menu dialog
- ;; note: dialog dimensions are calculated
- ;; automatically
- ;; usrmnuAttr -- 'normal' color attribute (defaults to
- ;; the standard TE/2 dialog normal attribute if
- ;; not specified
- ;; usrmnuHiAttr -- 'selected' color attribute (defaults to
- ;; the standard TE/2 dialog highligh attribute if
- ;; not specified
- ;; usrmnuTitle -- title string for the menu -- automatically
- ;; centered on the top row of the menu dialog
- ;; usrmnuItem1 thru
- ;; usrmnuItem10 -- fill in as many of these as you specified
- ;; in usrmnuItems, extra ones are ignored
- ;; the first character of each item should
- ;; be unique if you want mnemonic matching to
- ;; work well.
- ;;
- ;; The return code of this script is in usrmnuSelect. If the
- ;; user made a selection, the value of usrmnuSelect on exit will
- ;; be the item selected. If the user pressed ESCape to exit the
- ;; menu, the value will be zero.
- ;;
- ;;
- ;; Example:
- ;;
- ;; ;; MenuTest.scr
- ;; global integer usrmnuItems = 4
- ;; global integer usrmnuSelect = 1
- ;; global string usrmnuTitle = "Please Select One"
- ;; global string usrmnuItem1 = "Apples "
- ;; global string usrmnuItem2 = "Bananas "
- ;; global string usrmnuItem3 = "Coconuts "
- ;; global string usrmnuItem4 = "Dates "
- ;; global integer usrmnuTop = 10
- ;; global integer usrmnuLeft = 20
- ;; global integer usrmnuAttr = 0x1f
- ;; global integer usrmnuHiAttr = 0x71
- ;;
- ;; program
- ;; run("UserMenu")
- ;; if usrmnuSelect == 0
- ;; message("^M^JMenu choice aborted^M^J")
- ;; else
- ;; message("^M^JYou selected item %d^M^J", usrmnuSelect)
- ;; endif
- ;; end
- ;;
- ;;
- ;; -------------------------------------------------------------------------
-
- ;; -------------------------------------------------------------------------
- ;; GLOBAL variable
- global integer usrmnuSelect
- global integer usrmnuTop
- global integer usrmnuLeft
- global integer usrmnuAttr
- global integer usrmnuHiAttr
- global integer usrmnuItems
- global string usrmnuTitle
- global string usrmnuItem1
- global string usrmnuItem2
- global string usrmnuItem3
- global string usrmnuItem4
- global string usrmnuItem5
- global string usrmnuItem6
- global string usrmnuItem7
- global string usrmnuItem8
- global string usrmnuItem9
- global string usrmnuItem10
-
- ;; -------------------------------------------------------------------------
- ;; LOCAL Variables
- integer usrmnuBottom ;; Computed from usrmnuTop + usrmnuItems
- integer usrmnuRight ;; Computed from usrmnuLeft + string lengths
- integer usrmnuDLog ;; Dialog handle for menu box
- integer maxwid ;; Will be set to length of the longest string
- integer keyin ;; User keystroke for NavigateMenu
- integer fMatchedMnemonic ;; Return code from MatchMnemonic
- integer mattr ;; Temporary color attribute holder
- integer i ;; Temporary utility variable
-
- ;; -------------------------------------------------------------------------
-
- ;; -----------------------------------------------------------------
- ;; Using the defined Top and Left co-ordinates, the number of menu
- ;; items, and the length of the logest item (or title), this routine
- ;; computes usrmnuBottom and usrmnuRight for use by other routines
- ;; -----------------------------------------------------------------
-
- subroutine ComputeBottomRight
-
- maxwid = strlen(usrmnuTitle)
- if usrmnuItems > 0
- i = strlen(usrmnuItem1)
- if i > maxWid
- maxwid = i;
- endif
- endif
- if usrmnuItems > 1
- i = strlen(usrmnuItem2)
- if i > maxWid
- maxwid = i;
- endif
- endif
- if usrmnuItems > 2
- i = strlen(usrmnuItem3)
- if i > maxWid
- maxwid = i;
- endif
- endif
- if usrmnuItems > 3
- i = strlen(usrmnuItem4)
- if i > maxWid
- maxwid = i;
- endif
- endif
- if usrmnuItems > 4
- i = strlen(usrmnuItem5)
- if i > maxWid
- maxwid = i;
- endif
- endif
- if usrmnuItems > 5
- i = strlen(usrmnuItem6)
- if i > maxWid
- maxwid = i;
- endif
- endif
- if usrmnuItems > 6
- i = strlen(usrmnuItem7)
- if i > maxWid
- maxwid = i;
- endif
- endif
- if usrmnuItems > 7
- i = strlen(usrmnuItem8)
- if i > maxWid
- maxwid = i;
- endif
- endif
- if usrmnuItems > 8
- i = strlen(usrmnuItem9)
- if i > maxWid
- maxwid = i;
- endif
- endif
- if usrmnuItems > 9
- i = strlen(usrmnuItem10)
- if i > maxWid
- maxwid = i;
- endif
- endif
-
- usrmnuBottom = usrmnuTop + usrmnuItems + 4
- usrmnuRight = usrmnuLeft + maxwid + 4
-
- endsub
-
-
- ;; -----------------------------------------------------------------
- ;; Display or redisplay the menu. This routine displays the menu
- ;; items only (highlighting the appropriate one). It is called
- ;; at the beginning and after each keystroke that changes the menu
- ;; highlighted item. The menu dialog box and title are already
- ;; in place before the first call to this routine.
- ;; -----------------------------------------------------------------
-
- subroutine DisplayMenu
-
- if usrmnuItems > 0
- if usrmnuSelect == 0
- mattr = usrmnuHiAttr
- else
- mattr = usrmnuAttr
- endif
- strput(usrmnuTop+3, usrmnuLeft+2, mattr, "%s", usrmnuItem1)
- endif
- if usrmnuItems > 1
- if usrmnuSelect == 1
- mattr = usrmnuHiAttr
- else
- mattr = usrmnuAttr
- endif
- strput(usrmnuTop+4, usrmnuLeft+2, mattr, "%s", usrmnuItem2)
- endif
- if usrmnuItems > 2
- if usrmnuSelect == 2
- mattr = usrmnuHiAttr
- else
- mattr = usrmnuAttr
- endif
- strput(usrmnuTop+5, usrmnuLeft+2, mattr, "%s", usrmnuItem3)
- endif
- if usrmnuItems > 3
- if usrmnuSelect == 3
- mattr = usrmnuHiAttr
- else
- mattr = usrmnuAttr
- endif
- strput(usrmnuTop+6, usrmnuLeft+2, mattr, "%s", usrmnuItem4)
- endif
- if usrmnuItems > 4
- if usrmnuSelect == 4
- mattr = usrmnuHiAttr
- else
- mattr = usrmnuAttr
- endif
- strput(usrmnuTop+7, usrmnuLeft+2, mattr, "%s", usrmnuItem5)
- endif
- if usrmnuItems > 5
- if usrmnuSelect == 5
- mattr = usrmnuHiAttr
- else
- mattr = usrmnuAttr
- endif
- strput(usrmnuTop+8, usrmnuLeft+2, mattr, "%s", usrmnuItem6)
- endif
- if usrmnuItems > 6
- if usrmnuSelect == 6
- mattr = usrmnuHiAttr
- else
- mattr = usrmnuAttr
- endif
- strput(usrmnuTop+9, usrmnuLeft+2, mattr, "%s", usrmnuItem7)
- endif
- if usrmnuItems > 7
- if usrmnuSelect == 7
- mattr = usrmnuHiAttr
- else
- mattr = usrmnuAttr
- endif
- strput(usrmnuTop+10, usrmnuLeft+2, mattr, "%s", usrmnuItem8)
- endif
- if usrmnuItems > 8
- if usrmnuSelect == 8
- mattr = usrmnuHiAttr
- else
- mattr = usrmnuAttr
- endif
- strput(usrmnuTop+11, usrmnuLeft+2, mattr, "%s", usrmnuItem9)
- endif
- if usrmnuItems > 9
- if usrmnuSelect == 9
- mattr = usrmnuHiAttr
- else
- mattr = usrmnuAttr
- endif
- strput(usrmnuTop+12, usrmnuLeft+2, mattr, "%s", usrmnuItem10)
- endif
-
- endsub
-
-
- ;; -----------------------------------------------------------------
- ;; This routine scans the menu items for the first item who's first
- ;; character matches the current value of 'keyin'. Upper/lower case
- ;; conversion is handled. 'fMatchMnemonic' is set to 1 if a match
- ;; is found and usrmnuSelect is adjusted to the found item.
- ;;
- ;; Notice the method used for uppercase conversion. An alternative
- ;; would be to use:
- ;; i = asciival(toupper(usrmnuItemX))
- ;; or even:
- ;; i = asciival(toupper(strleft(usrmnuItemX, 1)))
- ;; but, in this specialized case, doing it in-line "by hand" is
- ;; probably quicker than re-entering the parser that many times.
- ;; -----------------------------------------------------------------
-
- subroutine MatchMnemonic
-
- fMatchedMnemonic = 0
- if (keyin >= 'a') AND (keyin <= 'z')
- keyin = keyin - 32
- endif
- if usrmnuItems > 0
- i = asciival(usrmnuItem1)
- if (i >= 'a') AND (i <= 'z')
- i = i - 32
- endif
- if i == keyin
- fMatchedMnemonic = 1
- usrmnuSelect = 0
- return
- endif
- endif
- if usrmnuItems > 1
- i = asciival(usrmnuItem2)
- if (i >= 'a') AND (i <= 'z')
- i = i - 32
- endif
- if i == keyin
- fMatchedMnemonic = 1
- usrmnuSelect = 1
- return
- endif
- endif
- if usrmnuItems > 2
- i = asciival(usrmnuItem3)
- if (i >= 'a') AND (i <= 'z')
- i = i - 32
- endif
- if i == keyin
- fMatchedMnemonic = 1
- usrmnuSelect = 2
- return
- endif
- endif
- if usrmnuItems > 3
- i = asciival(usrmnuItem4)
- if (i >= 'a') AND (i <= 'z')
- i = i - 32
- endif
- if i == keyin
- fMatchedMnemonic = 1
- usrmnuSelect = 3
- return
- endif
- endif
- if usrmnuItems > 4
- i = asciival(usrmnuItem5)
- if (i >= 'a') AND (i <= 'z')
- i = i - 32
- endif
- if i == keyin
- fMatchedMnemonic = 1
- usrmnuSelect = 4
- return
- endif
- endif
- if usrmnuItems > 5
- i = asciival(usrmnuItem6)
- if (i >= 'a') AND (i <= 'z')
- i = i - 32
- endif
- if i == keyin
- fMatchedMnemonic = 1
- usrmnuSelect = 5
- return
- endif
- endif
- if usrmnuItems > 6
- i = asciival(usrmnuItem7)
- if (i >= 'a') AND (i <= 'z')
- i = i - 32
- endif
- if i == keyin
- fMatchedMnemonic = 1
- usrmnuSelect = 6
- return
- endif
- endif
- if usrmnuItems > 7
- i = asciival(usrmnuItem8)
- if (i >= 'a') AND (i <= 'z')
- i = i - 32
- endif
- if i == keyin
- fMatchedMnemonic = 1
- usrmnuSelect = 7
- return
- endif
- endif
- if usrmnuItems > 8
- i = asciival(usrmnuItem9)
- if (i >= 'a') AND (i <= 'z')
- i = i - 32
- endif
- if i == keyin
- fMatchedMnemonic = 1
- usrmnuSelect = 8
- return
- endif
- endif
- if usrmnuItems > 9
- i = asciival(usrmnuItem10)
- if (i >= 'a') AND (i <= 'z')
- i = i - 32
- endif
- if i == keyin
- fMatchedMnemonic = 1
- usrmnuSelect = 9
- return
- endif
- endif
-
- endsub
-
-
- ;; -----------------------------------------------------------------
- ;; Collects keystrokes and maintains the menu.
- ;; -----------------------------------------------------------------
-
- subroutine NavigateMenu
-
- do
- keyin = getc()
- if (keyin == '^M') OR (keyin == '^[')
- break
- elseif (keyin & 0x000000ff)
- gosub MatchMnemonic
- if fMatchedMnemonic
- gosub DisplayMenu
- keyin = '^M'
- break
- else
- beep(1760, 50)
- endif
- else
- keyin = (keyin >> 8) & 0x000000ff
- if keyin == 72 ; UP
- usrmnuSelect = usrmnuSelect - 1
- if usrmnuSelect < 0
- usrmnuSelect = usrmnuItems - 1
- endif
- gosub DisplayMenu
- elseif keyin == 80 ; DOWN
- usrmnuSelect = usrmnuSelect + 1
- if usrmnuSelect >= usrmnuItems
- usrmnuSelect = 0
- endif
- gosub DisplayMenu
- else
- beep(1760, 50)
- endif
- endif
-
- loop
-
- if keyin == '^M'
- ;; user selected an item, adjust 'usrmnuSelect' back up to be 1-based
- usrmnuSelect = usrmnuSelect + 1
- else
- ;; user pressed ESCape, set 'usrmnuSelect' to 0
- usrmnuSelect = 0
- endif
-
- endsub
-
-
- ;; -----------------------------------------------------------------
- ;; Main driver for the menu
- ;; -----------------------------------------------------------------
-
- subroutine UserMenu
-
- ;; Make sure defaults are set if they are needed
- if usrmnuAttr == 0
- usrmnuAttr = DLogNormAttr
- endif
- if usrmnuHiAttr == 0
- usrmnuHiAttr = DLogHiAttr
- endif
-
- ;; Note that usrmnuSelect is maintained internally as zero-based and
- ;; will be changed back to one-based upon successful exit
- usrmnuSelect = usrmnuSelect - 1
- if (usrmnuSelect < 0) OR (usrmnuSelect >= usrmnuItems)
- usrmnuSelect = 0
- endif
-
- gosub ComputeBottomRight
- usrmnuDLog = opendialog(usrmnuTop, usrmnuLeft, usrmnuBottom, usrmnuRight, usrmnuAttr)
-
- ;; Place the title on the dialog
- i = usrmnuLeft + ((usrmnuRight - usrmnuLeft + 1 - strlen(usrmnuTitle)) / 2)
- strput(usrmnuTop+1, i, usrmnuAttr, "%s", usrmnuTitle)
-
- ;; Show it and run it
- gosub DisplayMenu
- gosub Navigatemenu
- closedialog(usrmnuDLog)
-
- endsub
-
-
- program
-
- if (usrmnuItems < 1) OR (usrmnuItems > 10)
- errormsg("Invalid number of Menu Items for UserMenu", "Must be from 1 to 10 items")
- usrmnuSelect = 0
- else
- gosub UserMenu
- endif
- end
-
-