home *** CD-ROM | disk | FTP | other *** search
- /*
- Program: GFReader()
- Purpose: Alternate modal read of a single GET.
- System: GRUMPFISH LIBRARY
- Author: Greg Lief
- Copyright (c) 1988-91, Greg Lief
- Clipper 5.01 Version
- Compile instructions: clipper gfreader /n/w/a
- */
-
- #include "getexit.ch"
- #include "grump.ch"
- #include "inkey.ch"
-
- #define MESSAGE 1
- #define PASSWORD cargo[2, 1]
- #define PASSWIDTH cargo[2, 2]
- #define PASSCHAR substr(oget:picture, 3)
-
- #define LISTVALUES oGet:cargo[3]
- #define LISTPOINTER oGet:cargo[4]
-
- #xtranslate UsingPassword() => ;
- oGet:picture != NIL .and. substr(oGet:picture, 1, 2) == "@P"
-
- #xtranslate ClearWarning() => ;
- restscreen(maxrow(), 0, maxrow(), maxcol(), warning) ; ;
- warning := ''
-
- //───── manifest constants for GFTimeout()
- #define TIMEOUT 1
- #define EXIT_EVENT 2
- #define WARNING 3
- #define WARN_EVENT 4
-
- #define WARN_COLOR "+w/r" // used for default warning message
- #define WARNING_ON ! empty(warning) // for readability
- #define WARNING_OFF empty(warning) // for readability
-
- function GFReader( oGet, bKeyproc )
- local mess_row, oldcursor, nkey, xx
- local nstart, ntimeout // used for warning/timeout testing
- local warning := '' // holds screen buffer when warning is issued
- local list_, ptr // used in conjunction with LIST clause
- local getlist // used for validating all GETs (VALIDATION)
-
- //───── read the GET if the WHEN condition is satisfied
- if ( GetPreValidate(oGet) )
- // activate the GET for reading
- mess_row := set(_SET_MESSAGE)
- if oGet:cargo != NIL .and. ! empty(oGet:cargo[MESSAGE])
- @ mess_row, 0 say padc( oGet:cargo[MESSAGE], maxcol() + 1)
- endif
- if UsingPassword()
-
- //───── if we have already been in this GET,
- //───── the cargo array will already contain 2 items
- if oGet:cargo != NIL .and. len(oGet:cargo) == 2
- oGet:varPut(padr(replicate(PASSCHAR, len(oGet:PASSWORD)), ;
- oGet:PASSWIDTH))
- else
- //───── determine if cargo is an array or not
- if oGet:cargo == NIL
- oGet:cargo := { NIL } // account for message slot
- endif
-
- //───── add subarray to cargo holding the following items:
- //───── 1) empty string to hold the contents of the password
- //───── 2) width of GET for padding later
- aadd(oGet:cargo, { '', len(oGet:varGet()) } )
-
- endif
-
- //───── test for LIST clause
- elseif oGet:cargo != NIL .and. len(oGet:cargo) > 1 .and. ;
- upper(oGet:cargo[2]) != "CALCULATOR"
-
- //───── if validation array has not already been created, do it now
- if len(oGet:cargo) < 3
-
- //───── loop through contents of list, looking for semi-colons
- //───── which serve as delimiters between possible choices
- list_ := {}
- do while ( ptr := at(';', oGet:cargo[2]) ) > 0
- aadd(list_, substr(oGet:cargo[2], 1, ptr - 1))
- oGet:cargo[2] := substr(oGet:cargo[2], ptr + 1)
- enddo
- aadd(list_, oGet:cargo[2]) // grab the rest of the beast
- aadd(oGet:cargo, list_) // add choices array to cargo
-
- //───── determine maximum length of list choices
- ptr := len(LISTVALUES[1])
- aeval(LISTVALUES, { | a | ptr := max(len(a), ptr) } )
-
- //───── if the GET is empty, stuff first list choice into it
- if empty( oGet:varGet() )
- oGet:varPut(LISTVALUES[1])
- endif
-
- //───── manipulate PICTURE to match longest length
- oGet:picture := replicate("X", ptr)
-
- aadd(oGet:cargo, 1) // cargo[4] will serve as placeholder
- endif
- //───── perform scan to determine where we are in the list
- //───── array and set the placeholder accordingly
- LISTPOINTER := ascan(LISTVALUES, ;
- { | ele | trim(ele) == trim(oGet:varGet()) } )
-
- endif
-
- oGet:SetFocus()
-
- //───── force cursor to end of the GET for password-style
- //───── if there is already data in this GET
- if UsingPassword()
- if ! empty(oGet:buffer)
- oGet:end()
- endif
- //───── check cargo for calculator style entry
- elseif oGet:cargo != NIL .and. len(oGet:cargo) > 1 .and. ;
- upper(oGet:cargo[2]) == "CALCULATOR"
- oldcursor := setcursor(0) // shut off cursor for cosmetics
- asize(oGet:cargo, 2)
- /*
- add subarray to cargo containing the following:
- 1) maximum number of decimals (use default picture clause
- if none provided with this GET)
- 2) running tab of decimal places used
- 3) flag indicating whether or not GET was already visited
- (.T. = already visited, .F. = not already visited). If
- when in GKCALC(), any key will clear out current entry
- */
- if oGet:picture == NIL
- oGet:picture := "#######.##"
- oGet:updatebuffer()
- endif
- aadd(oGet:cargo, { ;
- len(oGet:picture) - at('.', oGet:picture), ;
- 0, ;
- oGet:varGet() != 0 } )
- endif
- do while ( oGet:exitState == GE_NOEXIT )
- // check for initial typeout (no editable positions)
- if ( oGet:typeOut )
- oGet:exitState := GE_ENTER
- endif
-
- // apply keystrokes until exit
- do while ( oGet:exitState == GE_NOEXIT )
- nstart := seconds()
- if WARNING_OFF
- ntimeout := min( gftimeout(TIMEOUT), gftimeout(WARNING) )
- endif
- do while ( nkey := inkey() ) == 0 .and. seconds() - nstart < ntimeout
- if WARNING_ON
- gfsaveenv(, 0) // shut off cursor
- @ maxrow(), (maxcol() / 2) + 17 say ;
- ntimeout - seconds() + nstart picture '###' color WARN_COLOR
- gfrestenv()
- endif
- enddo
- do case
-
- //───── if we broke the loop with a keystroke, process it
- case nkey != 0
- eval(bKeyproc, oGet, nkey)
- if WARNING_ON
- ClearWarning()
- endif
-
- //───── check for warning
- case gftimeout(WARNING) == ntimeout .and. WARNING_OFF
- //───── save bottom row of screen and reset timeout seconds
- warning := savescreen(maxrow(), 0, maxrow(), maxcol())
- ntimeout := gftimeout(TIMEOUT) - gftimeout(WARNING)
- //───── run warning event if one was specified
- if ! empty(gftimeout(WARN_EVENT))
- eval(gftimeout(WARN_EVENT))
- else
- //───── default warning action
- gfsaveenv(, 0) // shut off cursor
- SCRNCENTER(maxrow(), ;
- padc("Seconds remaining before timeout:", maxcol()+1), ;
- WARN_COLOR)
- gfrestenv()
- endif
-
- //───── no warning -- process exit event if one was specified
- case ! empty(gftimeout(EXIT_EVENT))
- eval(gftimeout(EXIT_EVENT))
- if WARNING_ON
- ClearWarning()
- endif
-
- //───── timed out, no exit event, just stuff an ESC
- otherwise
- keyboard chr(K_ESC)
- if WARNING_ON
- ClearWarning()
- endif
-
- endcase
- enddo
-
- //───── if we were using a list...
- if oGet:cargo != NIL .and. len(oGet:cargo) > 3
- //───── because we padded the buffer for aesthetics,
- //───── we must now trim it before value is assigned
- oGet:varPut(trim(oGet:varGet()))
- endif
-
- // disallow exit if VALID condition is not satisfied
- if ( !GetPostValidate(oGet) )
- oGet:exitState := GE_NOEXIT
- endif
-
- enddo
-
- // remove message for this GET if there was one
- if oGet:cargo != NIL .and. ! empty(oGet:cargo[MESSAGE])
- scroll(mess_row, 0, mess_row, maxcol(), 0)
- endif
-
- // de-activate the GET
- oGet:KillFocus()
-
- //───── if password style entry was used, time to actually assign the value
- if UsingPassword()
- oGet:varPut(padr(oGet:PASSWORD, oGet:PASSWIDTH))
- endif
- endif
- setcursor(oldcursor)
- return nil
-
-
- /*
- Function: GFTimeOut()
- Purpose: Retrieve/assign values for warnings/timeouts/etc
- */
- function gftimeout(nitem, val)
- static settings_ := { 600000, , 600000, }
- local ret_val
- //───── if no parameters were passed, simply reset array
- if nitem == NIL
- settings_ := { 600000, , 600000, }
- else
- ret_val := settings_[nitem]
- if val != NIL
- settings_[nitem] := val
- endif
- endif
- return ret_val
-
- * eof GFREADER.PRG
-