home *** CD-ROM | disk | FTP | other *** search
- /*
- Function: LITE_MENU2()
- System: Grumpfish Library
- Author: Greg Lief
- Copyright (c) 1988-90 Greg Lief
- Dialect: Clipper 5.01
- Compile with: clipper litemen2 /n/w/a
- Purpose: Replacement for MENU TO... and ACHOICE()
-
- Warning: You must include the following line in your program if
- you want to use this function:
-
- #include "grumpm.ch"
-
- Caveat: Pretty minor, actually. In the same fashion that Clipper
- carries around a PUBLIC variable GETLIST for GETs, this
- function needs to use the variable MENULIST. Therefore,
- to avoid compiler warnings, you should include this line
- of code in your program somewhere:
-
- memvar menulist
- */
-
- //───── begin preprocessor directives
-
- #include "grump.ch"
- #include "inkey.ch"
-
- #define ROW 1
- #define COL 2
- #define PROMPT 3
- #define MESSAGE 4
- #define MESSAGECOLOR 5
- #define WHEN 6
- #define ACTION 7
- #define TRIGGERCOLOR 8
-
- #define FORWARD 1
- #define BACKWARD -1
-
- static unavacolor := '+n/n' // color for unavailable menu options
-
- //───── end preprocessor directives
-
- function lite_menu2(marray, plaincolor, selection, varname, bevent, ;
- ntimeout, bexit, trigcolor, cleft, cright)
- local num_elem := len(marray), xx, nkey := 0, luvletters := [], ;
- fallout := .f., oldmsgctr := set(_SET_MCENTER, .T.), ptr, ;
- mess_row := set(_SET_MESSAGE), oldcursor := setcursor(0), hilitcolor, ;
- oldcolor := setcolor(), direction := FORWARD, nstart
-
- //───── if no time-out was specified, use a ridiculous default
- default ntimeout to 100000000
-
- //───── if MESSAGE row was never set, use the bottom row of screen
- if mess_row == 0
- mess_row := maxrow()
- endif
-
- //───── set default colors for unselected, selected, and unavailable options
- default plaincolor to setcolor()
- xx := at(',', plaincolor)
- ptr := rat(',', plaincolor)
- if xx == ptr // this means only unselected & selected colors were passed
- hilitcolor := substr(plaincolor, xx + 1)
- else
- hilitcolor := substr(plaincolor, xx + 1, ptr - xx - 1)
- /*
- if a color string was passed that contains two commas, then use
- whatever lies to the right of the second comma as the color for
- unavailable menu options -- but if we are using the current
- color setting, instead use the default (+N/N) as defined above
- */
- if plaincolor != setcolor()
- unavacolor := substr(plaincolor, ptr + 1)
- endif
- endif
-
- //───── establish default color for highlighting trigger letters
- default trigcolor to "+" + plaincolor
-
- /*
- determine initial highlighted item default to 1 -- also perform
- error-checking to ensure they didn't specify an invalid selection
- */
- if selection == NIL .or. (selection < 1 .or. selection > num_elem)
- selection := 1
- endif
-
- //───── build the string containing available letters for selection
- for xx = 1 to num_elem
- /*
- first make sure that any WHEN clause for this option is
- satisfied, and that the option can therefore be selected
- */
- if marray[xx, WHEN] = NIL .or. eval( marray[xx, WHEN] )
- /*
- the default is to add the first non-space character.
- However, if there is a tilde embedded in this menu
- option, use the letter directly following it.
- */
- if (ptr := at("~", marray[xx, PROMPT]) ) > 0
- luvletters += upper(substr(marray[xx, PROMPT], ptr + 1, 1))
- else
- luvletters += upper(left(ltrim(marray[xx, PROMPT]), 1))
- endif
- else
- /* add placeholder CHR(255) for unavailable options */
- luvletters += chr(255)
- /* strip out any tildes now */
- marray[xx, PROMPT] = strtran(marray[xx, PROMPT], "~", "")
- endif
- ShowOption(marray[xx], plaincolor, trigcolor)
- next
- /*
- if LUVLETTERS is full of ASCII chr 255, that means there
- are no selectable menu options at this time - fall out
- */
- if luvletters == replicate(chr(255), num_elem)
- selection := 0
- else
- //───── commence main key-grabbing loop
- do while nkey != K_ENTER .and. nkey != K_ESC
- /* first make sure that current option is available for selection */
- if marray[selection, WHEN] == NIL .or. eval(marray[selection, WHEN])
- //───── then display current option in highlight color
- @ marray[selection, ROW], marray[selection, COL] ssay ;
- strtran(marray[selection, PROMPT], "~", "") color hilitcolor
-
- //───── display corresponding message if there is one
- if marray[selection, MESSAGE] == NIL
- scroll(mess_row, 0, mess_row, maxcol(), 0)
- else
- @ mess_row, 0 ssay padc(marray[selection, MESSAGE], maxcol() + 1) ;
- color if( marray[selection, MESSAGECOLOR] = NIL, plaincolor, ;
- marray[selection, MESSAGECOLOR] )
- endif
- if fallout
- exit
- else
- /*
- begin keypress wait loop -- necessary to accommodate
- recurring event and keyboard inactivity timeout
- */
- nstart := seconds()
- do while (nkey := inkey()) == 0 .and. seconds() - nstart < ntimeout
- if bevent != NIL
- eval(bevent)
- endif
- enddo
-
- //───── we timed out!
- if nkey == 0
- //───── if no exitevent was specified, use screen blanker
- if bexit == NIL
- blankscr3(-1)
- else
- eval(bexit)
- endif
- endif
- do case
-
- /*
- First, check for left and right arrow keypresses.
- If the LEFT and RIGHT clauses were used in conjunction
- with the MENU TO command, we must stuff characters into
- the buffer now. This would generally be used with a
- pull-down menu system.
- */
- case nkey == K_LEFT .and. cleft != NIL
- keyboard cleft
-
- case nkey == K_RIGHT .and. cright != NIL
- keyboard cright
-
- /*
- next, check for action block attached to last keypress
- if there is one, evaluate it and pass it the name of
- the MENU TO variable along with the current highlighted
- option (e.g., SEL[5] if you are on the fifth option)
- */
- case setkey(nkey) != NIL
- eval(setkey(nkey), procname(1), procline(1), varname + ;
- "[" + ltrim(str(selection)) + "]")
-
- //───── go down one line, observing wrap-around conventions
- case nkey == K_DOWN .or. nkey == K_RIGHT
- direction := FORWARD
- ShowOption(marray[selection], plaincolor, trigcolor)
- if selection == num_elem
- selection := 1
- else
- selection += direction
- endif
-
- //───── go up one line, observing wrap-around conventions
- case nkey == K_UP .or. nkey == K_LEFT
- direction := BACKWARD
- ShowOption(marray[selection], plaincolor, trigcolor)
- if selection == 1
- selection := num_elem
- else
- selection--
- endif
-
- //───── jump to top option
- case nkey == K_HOME
- //───── no point in changing color if we're already there
- if selection != 1
- ShowOption(marray[selection], plaincolor, trigcolor)
- selection := 1
- direction := FORWARD
- endif
-
- //───── jump to bottom option
- case nkey == K_END
- //───── no point in changing color if we're already there
- if selection != num_elem
- ShowOption(marray[selection], plaincolor, trigcolor)
- selection := num_elem
- direction := BACKWARD
- endif
-
- //───── first letter - jump to appropriate option
- case upper(chr(nkey)) $ luvletters
- ShowOption(marray[selection], plaincolor, trigcolor)
- selection := at(upper(chr(nkey)), luvletters)
- fallout := .t.
-
- endcase
- endif
- else
- //───── keep moving in current direction
- selection += DIRECTION
- //───── wrap-around
- if selection == 0
- selection := num_elem
- elseif selection > num_elem
- selection := 1
- endif
- endif
- enddo
- //───── if there is an action block attached to this selection, run it
- if lastkey() != K_ESC
- if marray[selection][ACTION] != NIL
- //───── reset cursor because this module might expect it on
- setcursor(oldcursor)
- eval(marray[selection][ACTION])
- //───── now that that's over with, turn the rascal back off
- setcursor(0)
- endif
- else
- selection := 0 // since they Esc'd out, return a zero
- endif
- endif
- setcursor(oldcursor)
- set(_SET_MCENTER, oldmsgctr) // reset SET MESSAGE CENTER
- setcolor(oldcolor)
- return selection
-
- * end function Lite_Menu2()
- *--------------------------------------------------------------------*
-
-
- /*
- Function: ShowOption()
- Purpose: Display current prompt in mixed colors
- */
- static function ShowOption(item, plaincolor, trigcolor)
- local ptr
- /* first make sure that this option is available for selection */
- if item[WHEN] = NIL .or. eval( item[WHEN] )
- if ( ptr := at("~", item[PROMPT]) ) > 0
- @ item[ROW], item[COL] ssay strtran(item[PROMPT], "~", "") ;
- color plaincolor
- @ item[ROW], item[COL] + ptr - 1 ssay substr(item[PROMPT], ptr + 1, 1) ;
- color if( empty(item[TRIGGERCOLOR]), trigcolor, item[TRIGGERCOLOR] )
- else
- @ item[ROW], item[COL] ssay left(item[PROMPT], 1) ;
- color if( empty(item[TRIGGERCOLOR]), trigcolor, item[TRIGGERCOLOR] )
- dispout(substr(item[PROMPT], 2), plaincolor)
- endif
- else
- //───── display unavailable menu options in gray on black
- @ item[ROW], item[COL] ssay item[PROMPT] color unavacolor
- endif
- return nil
-
- * end static function ShowOption()
- *--------------------------------------------------------------------*
-
- * eof litemen2.prg
-