home *** CD-ROM | disk | FTP | other *** search
- // Ogg's Menuing Module
- // (c) 1990 Nantucket Corporation
- //
- // Preliminary Version for Australian DevCon
- // Written by Craig Ogg
- //
-
- #include "omenu.ch"
- #include "inkey.ch"
- #include "arrayfun.ch"
-
- //....Clipper internal variables that this system depends on
- #define clpWRAP M->__wrap
-
- //....Default colors for menus
- #define omDEFBW "N/W,W+/W,W+/N,N/W,W/N"
- #define omDEFCLR "N/BG,R/BG,W+/R,W/BG,W/R"
-
- //....Amount of spaces to "pad" around menu items
- #define omPAD 2
-
- //....Positions in Menu Array Header
- #define mahLEN 10 // Length of array
- #define mahROW 1
- #define mahCOL 2
- #define mahLENGTH 3
- #define mahWIDTH 4
- #define mahCOLOR 5
- #define mahBORDER 6
- #define mahKEYS 7
- #define mahIDLE 8
- #define mahCHOICE 9
- #define mahLASTREQ 10
-
- //....Positions in Menu Array
- #define maLEN 9 // Length of this array
- #define maROW 1
- #define maCOL 2
- #define maCHOICE 3
- #define maACTION 4
- #define maCOLOR 5
- #define maACTIVE 6
- #define maHOTKEY 7 // Key that is "underlined"
- #define maKEYPOS 8 // Where that key is
- #define maIMAGE 9 // Image of Norm Selection
-
- //....Psuedo-functions
-
-
- //....MENULEN: Return length of menu
- //....
- //....menulen( <aMenu> ) ---> nLength
- //....
- FUNCTION MenuLen( aMenu )
- RETURN ( LEN( aMenu ) - 1 )
-
-
- //....ITEMNORM: Return normal menu item color from color string
- //....
- //....itemnorm( <cColor> ) --> cColor
- //....
- STATIC FUNCTION ItemNorm( cColor )
- RETURN LEFT( cColor, AT( ',', cColor ) - 1 )
-
-
- //....ITEMLETTER: Return color for hotkey from color string
- //....
- //....itemletter( <cColor> ) --> cColor
- //....
- STATIC FUNCTION ItemLetter( cColor )
-
- cColor := SUBSTR( cColor, AT(',',cColor)+1 )
-
- RETURN LEFT( cColor, AT(',',cColor)-1 )
-
-
- //....ITEMBOLD: RETURN selected menu item color from color string
- //....
- //....itembold( cColor ) --> cColor
- //....
- STATIC FUNCTION ItemBold( cColor)
-
- cColor := SUBSTR( cColor, AT(',',cColor)+1 )
- cColor := SUBSTR( cColor, AT(',',cColor)+1 ) // Second comma
-
- RETURN LEFT( cColor, AT(',',cColor)-1 )
-
-
- //....ITEMOFFNORM: Return inactivated menu item color from color string
- //....
- //....itemoffnorm( cColor ) --> cColor
- //....
- STATIC FUNCTION itemoffnorm( cColor )
-
- cColor := SUBSTR( cColor, AT(',',cColor)+1 )
- cColor := SUBSTR( cColor, AT(',',cColor)+1 ) // Second comma
- cColor := SUBSTR( cColor, AT(',',cColor)+1 ) // Third comma
-
- RETURN LEFT( cColor, AT(',',cColor)-1 )
-
-
- //....ITEMOFFBOLD: Return inactivated menu item bold color from color string
- //....
- //....itemoffbold( cColor ) --> cColor
- //....
- STATIC FUNCTION itemoffbold( cColor )
- RETURN SUBSTR( cColor, RAT( ',', cColor ) + 1 )
-
-
- //....CALCTOPLEFT: Calculate upper left corner of menu from size
- //....
- //....calctopleft( <nRow>, <nCol>,
- //.... <nHeight>, <nWidth>,
- //.... <nJust>, <pnTop>,
- //.... <pnLeft> ) ---> NIL
- //....
- //....Paramters:
- //.... nRow,nCol - Reference row and column
- //.... nHeight - Height of menu in rows
- //.... nWidth - Width of menu in columns
- //.... nJust - One of the following:
- //.... omCENTER - Center menu around nRow,nCol
- //.... omRIGHT - Right justify menu against nRow,nCol
- //.... omLEFT - Left justify menu against nRow,nCol
- //.... pnTop - Resulting top coordinate, must be passed by reference
- //.... pnLeft - Resulting left coordinate, must be passed by reference
- //....
- STATIC FUNCTION calctopleft( nRow, nCol, nHeight, nWidth, nJust, pnTop, pnLeft )
-
- DO CASE
- CASE nJust == omLEFT
- pnTop := nRow
- pnLeft := nCol
- CASE nJust == omRIGHT
- pnTop := nRow
- pnLeft := ( nCol - nWidth ) + 1
- CASE nJust == omCENTER
- pnTop := nRow - INT( nHeight / 2 )
- pnLeft := nCol - INT( nWidth / 2 )
- OTHERWISE
- pnTop := nRow
- pnLeft := nCol
- ENDCASE
-
- IF pnTop < 1
- pnTop := 1
- ENDIF
-
- IF pnLeft < 0
- pnLeft := 0
- ENDIF
-
- RETURN( NIL )
-
-
- //....ADDDEFAULTKEYS : Add default keys to the Key Handler Array
- //....
- //....adddefaultkeys( <aKeyArray> ) --> aKeyArray
- //....
- //....Paramters:
- //.... aKeyArray : Key Handler Array to make copy of and add default
- //.... keys to
- //....
- STATIC FUNCTION adddefaultkeys( aKeyArray )
-
- LOCAL aKey := {}, i
-
- //....Done this way to handle 0 length key arrays
- //....Replace with asize() when asize works
-
- IF LEN(aKeyArray) > 0
- aKey := ARRAY( LEN( aKeyArray ) )
- ACOPY( aKeyArray, aKey )
- ENDIF
-
- AADD( aKey, { K_UP, {|aMenu,nKey| MenuUp( aMenu )} } )
- AADD( aKey, { K_DN, {|aMenu,nKey| MenuDown( aMenu )} } )
- AADD( aKey, { K_HOME, {|aMenu,nKey| ItemMark( aMenu, 1 )} } )
- AADD( aKey, { K_CTRLPGUP, {|aMenu,nKey| ItemMark( aMenu, 1 )} } )
- AADD( aKey, { K_END, {|aMenu,nKey| ItemMark( aMenu, MenuLen(aMenu) )} } )
- AADD( aKey, { K_CTRLPGDN, {|aMenu,nKey| ItemMark( aMenu, MenuLen(aMenu) )} } )
- AADD( aKey, { K_ESC, {|aMenu,nKey| MenuExit( aMenu )} } )
- AADD( aKey, { K_ RETURN, {|aMenu,nKey| MenuDoAction( aMenu )} } )
-
- RETURN aKey
-
-
- //....MENUCREATE: Create menu "object"
- //....
- //....MenuCreate( <nRow>, <nCol>, <nJust>, [<cMenuColor>], [<nBorder>], ;
- //.... <aChoices>, [<aKeys>], [<aIdle>] ) ---> aMenu
- //....
- //....Parameters:
- //....
- //.... nRow - Row coordinate
- //.... nCol - Column coordinate
- //.... nJust - One of the following:
- //.... omCENTER - Center menu around nRow,nCol
- //.... omRIGHT - Right justify menu against nRow,nCol
- //.... omLEFT - Left justify menu against nRow,nCol
- //.... nBorder - One of the following:
- //.... omDOUBLE - Double line border
- //.... omSINGLE - Single line border
- //.... omNONE - No line around border
- //.... aChoices - An array of arrays of type { cChoice, bAction, cColor, lActive }
- //.... aKeys - An array of arrays of type { nKey, bAction }
- //.... aIdle - An array of arrays of type { nIdleSecs, bAction }
- //....
- //.... RETURNs:
- //....
- //.... aMenu - A menu "object"
- //....
- FUNCTION MenuCreate( nRow, nCol, nJust, cMenuColor, nBorder, aChoices, aKeys, aIdle )
-
- LOCAL aMenu := { NIL }, aElement, aText := {}
- LOCAL nMaxlen := 0, nTop, nLeft
- LOCAL cChoice
- LOCAL nChoice
-
- //.... create array of menu choice text
- AEVAL( aChoices, {|x| AADD( aText, x[1] )} )
-
- //.... determine length of longest choice
- nMaxlen := LEN( acomp( aText, acMAXLEN ) ) - 1
-
- calctopleft( nRow, nCol, LEN( aText ) + 2, nMaxlen + 4, ;
- nJust, @nTop, @nLeft )
-
- //.... first element of aMenu is reserved for "header"
- aMenu[1] := ARRAY( mahLEN )
-
- //.... sort idle events in descending order
- IF aIdle == NIL
- aIdle := {}
- ENDIF
-
- //.... setup header information
- aMenu[1, mahROW] := nTop
- aMenu[1, mahCOL] := nLeft
- aMenu[1, mahLENGTH] := LEN( aText ) + 2
- aMenu[1, mahWIDTH] := nMaxlen + IIF( nBorder == omNONE, omPAD * 2, ;
- ( omPAD * 2 ) + 2 )
- aMenu[1, mahCOLOR] := IIF( cMenuColor != NIL, itemnorm( cMenuColor ), ;
- IIF( ISCOLOR(), itemnorm( omDEFCLR ), ;
- itemnorm( omDEFBW ) ) )
- aMenu[1, mahBORDER] := IIF( nBorder != NIL, nBorder, omNONE )
- aMenu[1, mahKEYS] := IIF( aKeys == NIL, AddDefaultKeys( {} ), ;
- AddDefaultKeys( aKeys ) )
- aMenu[1, mahIDLE] := aIdle
-
- //.... fill in the choices
- nRow := nTop + 1
- nCol := nLeft + IIF( nBorder == omNONE, 0, 1 )
- FOR nChoice := 1 TO LEN( aText )
- //....completely define one menu choice
- aElement := ARRAY( maLEN )
-
- aElement[maROW] := nRow++
- aElement[maCOL] := nCol
-
- IF aText[nChoice] == '-'
- //....force hotkey indicator
- aElement[maKEYPOS] := 0
- aElement[maHOTKEY] := ''
-
- aElement[maCHOICE] := aText[nChoice]
- ELSE
- cChoice := SPACE( omPAD ) + aText[nChoice]
-
- //....find hotkey indicator
- aElement[maKEYPOS] := AT( '~', cChoice )
- aElement[maHOTKEY] := SUBSTR( cChoice, aElement[maKEYPOS] + 1, 1 )
-
- aElement[maCHOICE] := SPACE( omPAD ) + ;
- PAD( STRTRAN( aText[nChoice], '~', '' ), nMaxlen ) + ;
- SPACE( omPAD )
- ENDIF
-
- aElement[maACTION] := IIF( aChoices[nChoice, 2] == NIL, ;
- {|menu| MenuExit(menu)}, ;
- aChoices[nChoice, 2] )
-
- IF aChoices[nChoice, 3] != NIL
- aElement[maCOLOR] := aChoices[nChoice, 3]
- ELSE
- IF cMenuColor != NIL
- //....use menu color if item color not given
- aElement[maCOLOR] := cMenuColor
- ELSE
- //....use default color setting if neither given
- aElement[maCOLOR] := IIF( ISCOLOR(), omDEFCLR, omDEFBW )
- ENDIF
- ENDIF
-
- //....make option active if not specified
- aElement[maACTIVE] := iif( aChoices[nChoice,4] != NIL, ;
- aChoices[nChoice, 4], ;
- .T. )
- AADD( aMenu, aElement )
- NEXT
-
- RETURN aMenu
-
-
- //....ITEMISLINE: Is item a line?
- //....
- //....ItemIsLine( <aMenu>, [<nChoice>] ) ---> lLine
- //....
- FUNCTION ItemIsLine( aMenu, nChoice )
-
- IF nChoice == NIL
- nChoice := MenuChoice( aMenu )
- ENDIF
-
- RETURN( aMenu[ nChoice + 1, maCHOICE ] == '-' )
-
-
- //....ITEMISACTIVE: Is item active
- //....
- //....ItemIsActive( <aMenu>, [<nChoice>] ) ---> lActive
- //....
- FUNCTION ItemIsActive( aMenu, nChoice )
-
- IF nChoice == NIL
- nChoice := MenuChoice( aMenu )
- ENDIF
-
- RETURN( aMenu[ nChoice + 1, maACTIVE ] )
-
-
- //....ITEMOFF: Make item inactive
- //....
- //....ItemOff( <aMenu>, [<nChoice>] ) ---> aMenu
- //....
- FUNCTION ItemOff( aMenu, nChoice )
-
- IF nChoice == NIL
- nChoice := MenuChoice( aMenu )
- ENDIF
-
- //....Set item to unselectable
- aMenu[ nChoice + 1, maACTIVE ] := .F.
-
- ItemShow( aMenu, nChoice )
-
- RETURN aMenu
-
-
- //....ITEMON: Make item active
- //....
- //....ItemOn( <aMenu>, [<nChoice>] ) ---> aMenu
- //....
- FUNCTION ItemOn( aMenu, nChoice )
-
- IF nChoice == NIL
- nChoice := MenuChoice( aMenu )
- ENDIF
-
- //....Set item to selectable
- aMenu[ nChoice + 1, maACTIVE ] := .T.
-
- ItemShow( aMenu, nChoice )
-
- RETURN aMenu
-
-
- //....ITEMSHOW: Show choice in specified color setting
- //....
- //....ItemShow( <aMenu>, [<nChoice>] ) ---> aMenu
- //....
- FUNCTION ItemShow( aMenu, nChoice )
-
- LOCAL nRow, nCol
- LOCAL cOldColor
-
- cOldColor := SETCOLOR()
-
- IF nChoice == NIL
- nChoice := MenuChoice( aMenu )
- ENDIF
-
- nRow := aMenu[nChoice + 1,maROW]
- nCol := aMenu[nChoice + 1,maCOL]
-
- DO CASE
- CASE ItemIsLine( aMenu, nChoice )
- //....Line all the way across
- SETCOLOR( aMenu[1, mahCOLOR] )
-
- DO CASE
- CASE aMenu[1, mahBORDER] == omNONE
- @ nRow, aMenu[1, mahCOL] SAY REPLICATE( '─', aMenu[1, mahWIDTH] )
-
- CASE aMenu[1, mahBORDER] == omSINGLE
- @ nRow, aMenu[1, mahCOL] SAY REPLICATE( '─', aMenu[1, mahWIDTH] )
- @ nRow, aMenu[1, mahCOL] SAY '├'
- @ nRow, ( aMenu[1, mahCOL] + aMenu[1, mahWIDTH] - 1 ) SAY '┤'
-
- CASE aMenu[1, mahBORDER] == omDOUBLE
- @ nRow, aMenu[1, mahCOL] SAY REPLICATE( '─', aMenu[1, mahWIDTH] )
- @ nRow, aMenu[1, mahCOL] SAY '╟'
- @ nRow, ( aMenu[1, mahCOL] + aMenu[1, mahWIDTH] - 1 ) SAY '╢'
-
- ENDCASE
-
- CASE nChoice == MenuChoice( aMenu )
- //....Item is current choice
- //....Show item in bold color
- IF ItemIsActive( aMenu, nChoice )
- SETCOLOR( itembold( aMenu[nChoice + 1,maCOLOR] ) )
- ELSE
- SETCOLOR( itemoffbold( aMenu[nChoice + 1,maCOLOR] ) )
- ENDIF
- @ nRow, nCol SAY aMenu[nChoice + 1,maCHOICE]
-
- CASE (.NOT. ItemIsActive( aMenu, nChoice ))
- //....Item not selectable
- //....Show item in inactive color
- SETCOLOR( itemoffnorm( aMenu[nChoice + 1,maCOLOR] ) )
- @ nRow, nCol SAY aMenu[nChoice + 1,maCHOICE]
-
- OTHERWISE
- //....Normal menu item
-
- IF aMenu[ nChoice + 1, maIMAGE] == NIL
- //....Show item in normal color
- SETCOLOR( itemnorm( aMenu[nChoice + 1,maCOLOR] ) )
- @ nRow, nCol SAY aMenu[nChoice + 1,maCHOICE]
-
- //....Write over hotkey letter with letter in appropriate color
- SETCOLOR( itemletter( aMenu[nChoice + 1,maCOLOR] ) )
- @ nRow, (nCol+aMenu[nChoice + 1,maKEYPOS]-1) SAY aMenu[nChoice + 1,maHOTKEY]
-
- aMenu[nChoice + 1,maIMAGE] := SAVESCREEN( nRow, nCol, ;
- nRow, nCol + LEN( aMenu[nChoice + 1,maCHOICE] ) - 1 )
- ELSE
- RESTSCREEN( nRow, nCol, ;
- nRow, nCol + LEN( aMenu[nChoice + 1,maCHOICE] ) - 1, ;
- aMenu[nChoice + 1, maIMAGE ] )
- ENDIF
-
- ENDCASE
-
- SETCOLOR(cOldColor)
-
- RETURN aMenu
-
-
- //....ItemMark: Set choice to current choice and highlight it
- //....
- //....ItemMark( <aMenu>, <nChoice> ) ---> aMenu
- //....
- FUNCTION ItemMark( aMenu, nChoice )
-
- LOCAL nRow, nCol, nOldChoice
- LOCAL cOldColor
-
- nOldChoice := MenuChoice( aMenu )
-
- //....Set item to current item
- aMenu[ 1, mahCHOICE ] := nChoice
-
- IF nOldChoice != NIL
- ItemShow( aMenu, nOldChoice )
- ENDIF
-
- ItemShow( aMenu, nChoice )
-
- RETURN aMenu
-
-
- //....DRAWOUTLINE: Draw outline of menu w/ appropriate border
- //....
- //....drawoutline( <aMenu> ) ---> aMenu
- //....
- STATIC FUNCTION DrawOutline( aMenu )
-
- LOCAL cOldColor
- LOCAL nRow, nCol, nEndRow, nEndCol
-
- cOldColor := SETCOLOR()
- nRow := aMenu[ 1, mahROW ]
- nCol := aMenu[ 1, mahCOL ]
- nEndRow := nRow + aMenu[ 1, mahLENGTH ] - 1
- nEndCol := nCol + aMenu[ 1, mahWIDTH ] - 1
-
- SETCOLOR( aMenu[ 1, mahCOLOR ] )
-
- @ nRow, nCol CLEAR TO nEndRow, nEndCol
-
- DO CASE
- CASE aMenu[ 1, mahBORDER ] == omSINGLE
- @ nRow, nCol TO nEndRow, nEndCol
- CASE aMenu[ 1, mahBORDER ] == omDOUBLE
- @ nRow, nCol TO nEndRow, nEndCol DOUBLE
- ENDCASE
-
- RETURN aMenu
-
-
- //....MENUSETREQ: Set last action
- //....
- //....MenuSetReq( <aMenu>, <nAction> ) ---> aMenu
- //....
- FUNCTION MenuSetReq( aMenu, nAction )
-
- aMenu[ 1, mahLASTREQ ] := nAction
-
- RETURN aMenu
-
-
- //....MENUEXIT: Exit Menu
- //....
- //....MenuExit( <aMenu> ) ---> aMenu
- //....
- FUNCTION MenuExit( aMenu )
-
- MenuSetReq( aMenu, omEXIT )
-
- RETURN( aMenu )
-
-
- //....MENUABORT: Exit Menu and clear choice
- //....
- //....MenuAbort( <aMenu> ) ---> aMenu
- //....
- FUNCTION MenuAbort( aMenu )
-
- aMenu[1, mahCHOICE] := 0
- MenuSetReq( aMenu, omEXIT )
-
- RETURN( aMenu )
-
-
- //....MenuLastReq: RETURN last action
- //....
- //....MenuLastReq( <aMenu> ) ---> nAction
- //....
- STATIC FUNCTION MenuLastReq( aMenu )
- RETURN( aMenu[ 1, mahLASTREQ ] )
-
-
- //....MENUCHOICE: RETURN current choice
- //....
- //....menuchoice( <aMenu> ) ---> nChoice
- //....
- FUNCTION MenuChoice( aMenu )
- RETURN( aMenu[ 1, mahCHOICE ] )
-
-
- //....DOIDLEEVENTS: Do Idle events, called once every second
- //....
- //....DoIdleEvents( aMenu, nSecsElapsed ) ---> aMenu
- //....
- //....NOTE: An event will be called every MOD of its elapsed value
- //....
- //....Only one event will be called per pass, if there is more than one
- //....the first one will be called
- //....
- STATIC FUNCTION doidleevents( aMenu, nSecsElapsed )
-
- LOCAL aIdleEvents := aMenu[ 1, mahIDLE ]
- LOCAL i := 1, nNumEvents
- LOCAL lExit := .F.
-
- #ifdef DEBUG
- @ 20,0
- @ 20,0 say 'Idle: ' + ltrim(str(nSecsElapsed))
- #endif
-
- IF (nNumEvents := len(aIdleEvents)) == 0
- lExit := .T.
- ENDIF
-
- DO WHILE (.NOT. lExit) .AND. i <= nNumEvents
- IF (nSecsElapsed % aIdleEvents[i, 1]) == 0
- #ifdef DEBUG
- ?? ' Matched Event: ' + ltrim(str(i))
- #endif
-
- lExit = .T.
-
- SET CURSOR ON
- EVAL( aIdleEvents[i,2], aMenu, nSecsElapsed )
- SET CURSOR OFF
- ENDIF
- i++
- ENDDO
-
- RETURN( aMenu )
-
-
- //....DOKEYEVENTS: Do Key events, called once every time a key is hit
- //....
- //....DoKeyEvents( aMenu, nKey ) ---> aMenu
- //....
- //....NOTE: If key multiply defined, it will only be called once, and an
- //.... event with a key value of NIL will be called if no other
- //.... events match.
- //....
- STATIC FUNCTION dokeyevents( aMenu, nKey )
-
- LOCAL aKeyEvents := aMenu[ 1, mahKEYS ]
- LOCAL nCurrEvent, nChoice
- LOCAL lExit := .F.
-
- //....Check for Menu Item Keys first
- nChoice := ASCAN( aMenu, ;
- {|x| IIF(x[maCHOICE] == '-', .F., IIF(x[maACTIVE], ;
- (UPPER(x[maHOTKEY]) == UPPER(CHR(nKey))), .F.) )}, 2 )
- IF nChoice != 0
- ItemMark( aMenu, nChoice - 1 )
- MenuDoAction( aMenu )
- ELSE
- //....If not one of the hotkeys, handle regular key events
- IF (nCurrEvent := ASCAN( aKeyEvents, {|x| x[1] == nKey} )) == 0
- //....Not any defined key so find NIL and execute it
- //....Replace with ascan when ascan will find NILs
- nCurrEvent := 1
- DO WHILE ( .NOT. lExit ) .AND. ( nCurrEvent <= LEN( aKeyEvents ) )
- IF aKeyEvents[ nCurrEvent, 1 ] == NIL
- SET CURSOR ON
- EVAL( aKeyEvents[nCurrEvent,2], aMenu, nKey )
- SET CURSOR OFF
-
- lExit := .T.
- ENDIF
-
- nCurrEvent++
- ENDDO
- ELSE
- SET CURSOR ON
- EVAL( aKeyEvents[nCurrEvent,2], aMenu, nKey )
- SET CURSOR OFF
- ENDIF
- ENDIF
-
- RETURN( aMenu )
-
-
- //....MENUDOACTION: Do code block associated with current choice
- //....
- //....MenuDoAction( <aMenu> ) ---> aMenu
- //....
- FUNCTION MenuDoAction( aMenu )
-
- IF ItemIsActive( aMenu, MenuChoice( aMenu ) )
- EVAL( aMenu[MenuChoice( aMenu )+1,maACTION], aMenu )
- ENDIF
-
- RETURN( aMenu )
-
-
- //....MENUACTIVATE: Display and "turn on" menu
- //....
- //....MenuActivate( <aMenu>, [<nChoice>] ) ---> aMenu
- //....
- FUNCTION MenuActivate( aMenu, nChoice )
-
- LOCAL nCurrTime, nLastTime, nCtrlTime, nKey
- LOCAL cScreen
- LOCAL i
-
- IF nChoice == NIL
- nChoice := 1
- ENDIF
-
- SAVE SCREEN TO cScreen
- SET CURSOR OFF
-
- aMenu[1,mahCHOICE] := NIL
- drawoutline( aMenu )
- FOR i := 1 TO menulen( aMenu )
- ItemShow( aMenu, i )
- NEXT
- ItemMark( aMenu, nChoice )
-
- nCtrlTime := nLastTime := INT( SECONDS() )
- MenuSetReq( aMenu, omCONT )
-
- DO WHILE MenuLastReq( aMenu ) == omCONT
- nKey = INKEY()
- IF nKey != 0
- DoKeyEvents( aMenu, nKey )
-
- //....Reset idle time counter
- nCtrlTime := nLastTime := INT( SECONDS() )
- ENDIF
-
- IF MenuLastReq( aMenu ) == omCONT
- //....Handle Idle Events
-
- //....Make sure that we are getting EXACTLY one second resolution
- //....so that no events are skipped and we don't check for idle
- //....events too often
- nCurrTime := INT( SECONDS() )
- IF nCurrTime >= (nCtrlTime+1)
- nCurrTime := (nCtrlTime+1)
-
- DoIdleEvents( aMenu, nCurrTime-nLastTime )
-
- //....Move forward one second
- nCtrlTime := nCurrTime
- ENDIF
- ENDIF
- ENDDO
-
- RESTORE SCREEN FROM cScreen
- SET CURSOR ON
-
- RETURN( aMenu )
-
-
- //....MENUDOWN: Move to next option down the list
- //....
- //....MenuDown( <aMenu> ) ---> aMenu
- //....
- FUNCTION MENUDOWN( aMenu )
-
- LOCAL nOldChoice := MenuChoice( aMenu )
- LOCAL nNewChoice
-
- SET CURSOR OFF
-
- nNewChoice := nOldChoice + 1
-
- IF MenuChoice( aMenu ) == menulen( aMenu )
- IF clpWRAP
- ItemMark( aMenu, 1 )
- ItemShow( aMenu, nOldChoice )
- ENDIF
- ELSE
- DO WHILE ItemIsLine( aMenu, nNewChoice )
- nNewChoice++
- ENDDO
- ItemMark( aMenu, nNewChoice )
- ItemShow( aMenu, nOldChoice )
- ENDIF
-
- SET CURSOR ON
-
- RETURN( aMenu )
-
-
- //....MENUUP: Move to next option up the list
- //....
- //....menuup( <aMenu> ) ---> aMenu
- //....
- FUNCTION MENUUP( aMenu )
-
- LOCAL nOldChoice := MenuChoice( aMenu )
- LOCAL nNewChoice
-
- SET CURSOR OFF
-
- nNewChoice := nOldChoice - 1
-
- IF MenuChoice( aMenu ) == 1
- IF clpWRAP
- ItemMark( aMenu, menulen( aMenu ) )
- ItemShow( aMenu, nOldChoice )
- ENDIF
- ELSE
- DO WHILE ItemIsLine( aMenu, nNewChoice )
- nNewChoice--
- ENDDO
- ItemMark( aMenu, nNewChoice )
- ItemShow( aMenu, nOldChoice )
- ENDIF
-
- SET CURSOR ON
-
- RETURN( aMenu )
-