home *** CD-ROM | disk | FTP | other *** search
- // Tbutils.prg
- //
- // Utility routines for TBrowse and TBColumn classes
- //
- // Export:
- // MyTBColumnNew - Create TBColumn object, allows setting of all i vars
- // MyTBrowseNew - Same for TBrowse object
- // TBCClone - Return a clone of an existing TBrowse object
- // TBClone - Return a clone of an existing TBColumn object
- // TBMsg - Display a message at maxrow() without side-effect
- // FullStabilize - Repeatedly call stabilize until it returns .T.
- // KeyStabilize - Repeatedly call stabilize until it returns .T.
- // OR the user presses a key. Returns .T. if stabilized,
- // .F. if key pressed. Does not remove key from buffer
- // StdMeth - Simple routine performing the defuaklt mapping of
- // keys to methods
- // NumVisibleRows - Returns number of visible data rows
- //
- // TBCColPos - Returns array containing column position of
- // each visible column
- // TBWhSkip - SkipBlock function implementing general purpose
- // while condition
- // TBWhStart - goTopBlock function implementing general purpose
- // while condition
- // TBWhEnd - goBottomBlock function implementing general
- // purpose while condition
- // TBForStart - GoTopBlock function implementing general purpose
- // for condition
- // TBForEnd - GoBottomBlock function implementing general
- // purpose for condition
- // TBForSkip - SkipBlock function implementing general purpose
- // for condition
- // TBFwFirst - goTopBlock function implementing general purpose
- // for and while condition
- // TBFwLast - goBottomBlock function implementing general
- // purpose for and while condition
- // TBFwSkip - skipBlock function implementing general
- // purpose for and while condition
- // AddAllFields - Add all fields in current database as TBColumns
- // to the passed TBrowse object
- // DbSkipBlock - Abstracted skipblock for database browsing
- // DbStabilize - Repeatedly call stabilize until it returns .T.,
- // ensuring the same record is highlighted (for
- // database edits)
- // TBForWhile - Return TBrowse object implementing for and
- // while conditions. Pass as blocks.
- // TBFwGoNext - Move to next record with for and while condition
- // set. Return .T. if moved, otherwise .F.
- // TBFwGoPrev - Move to previous record with for and while
- // condition set. Return .T. if moved, otherwise .F.
- // TBaGoLast - Go to last record supporting append mode
- // TBaGoFirst - Go to first record supporting append mode
- // TBaGoNext - Go to next record supporting append mode
- // TBaGoPrev - Go to previous record supporting append mode
- // TBfwaFirst - TBrowse routine called by goTopBlock. fwa stands for
- // "for/while/append". It supports generic for and while
- // conditions and append mode.
- // TBfwaLast - Routine called by goBottomBlock to move to the last
- // record in the database matching the for and while
- // condition, and taking append mode into account.
- // TBfwaGoNext - Move to next record supporting for and while
- // conditions and append mode
- // TBfwaGoPrev - Move to previous record record supporting for and
- // while conditions and append mode
- // TBfwaBrowse - Sets up TBrowse object for a browse with a while
- // and for condition and append mode
-
- // Compile with /a /m /n /w
-
- #include "inkey.ch"
- #include "Tbutils.ch"
-
- #define SET_IVAR(iVar, p) iVar := iif(p != NIL, p, iVar)
-
- FUNCTION MyTBColumnNew(bBlock, cargo, bColorBlock, cColSep, ;
- aDefColor, cFooting, cFootSep, cHeading, ;
- cHeadSep, nWidth)
-
- LOCAL oTbc := TBColumnNew()
-
- SET_IVAR(oTbc:block, bBlock)
- SET_IVAR(oTbc:cargo, cargo)
- SET_IVAR(oTbc:colorBlock, bColorBlock)
- SET_IVAR(oTbc:colSep, cColSep)
- SET_IVAR(oTbc:defColor, aDefColor)
- SET_IVAR(oTbc:footing, cFooting)
- SET_IVAR(oTbc:footSep, cFootsep)
- SET_IVAR(oTbc:heading, cHeading)
- SET_IVAR(oTbc:headSep, cHeadSep)
- SET_IVAR(oTbc:width, nWidth)
-
- RETURN oTbc
-
-
- FUNCTION MyTBrowseNew(lAutoLite, cargo, cColorSpec, nColPos, ;
- cColSep, cFootSep, nFreeze, bGoBottomBlock, ;
- bGoTopBlock, cHeadSep, lHitBottom, lHitTop, ;
- nBottom, nLeft, nRight, nTop, nRowPos, ;
- bSkipBlock, lStable)
-
- LOCAL oTbr := TBrowseNew()
-
- SET_IVAR(oTbr:autoLite, lAutoLite)
- SET_IVAR(oTbr:cargo, cargo)
- SET_IVAR(oTbr:colorSpec, cColorSpec)
- SET_IVAR(oTbr:colPos, nColPos)
- SET_IVAR(oTbr:colSep, cColSep)
- SET_IVAR(oTbr:footSep, cFootSep)
- SET_IVAR(oTbr:freeze, nFreeze)
- SET_IVAR(oTbr:goBottomBlock, bGoBottomBlock)
- SET_IVAR(oTbr:goTopBlock, bGoTopBlock)
- SET_IVAR(oTbr:headSep, cHeadSep)
- SET_IVAR(oTbr:hitBottom, lHitBottom)
- SET_IVAR(oTbr:hitTop, lHitTop)
- SET_IVAR(oTbr:nBottom, nBottom)
- SET_IVAR(oTbr:nLeft, nLeft)
- SET_IVAR(oTbr:nRight, nRight)
- SET_IVAR(oTbr:nTop, nTop)
- SET_IVAR(oTbr:rowPos, nRowPos)
- SET_IVAR(oTbr:skipBlock, bSkipBlock)
- SET_IVAR(oTbr:stable, lStable)
-
- RETURN oTbr
-
-
- FUNCTION TBClone(oTbcOld)
-
- LOCAL oTbcNew := TBColumnNew()
-
- oTbcNew:block := oTbcOld:block
- oTbcNew:cargo := oTbcOld:cargo
- oTbcNew:colorBlock := oTbcOld:colorBlock
- oTbcNew:defColor := oTbcOld:defColor
- oTbcNew:footing := oTbcOld:footing
- oTbcNew:footSep := oTbcOld:footSep
- oTbcNew:heading := oTbcOld:heading
- oTbcNew:headSep := oTbcOld:headSep
- oTbcNew:width := oTbcOld:width
-
- RETURN oTbcNew
-
-
- FUNCTION TBRClone(oTbrOld)
-
- LOCAL oTbrNew := TBrowseNew()
-
- oTbrNew:autoLite := oTbrOld:autoLite
- oTbrNew:cargo := oTbrOld:cargo
- oTbrNew:colorSpec := oTbrOld:colorSpec
- oTbrNew:colPos := oTbrOld:colPos
- oTbrNew:footSep := oTbrOld:footSep
- oTbrNew:freeze := oTbrOld:freeze
- oTbrNew:goBottomBlock := oTbrOld:goBottomBlock
- oTbrNew:goTopBlock := oTbrOld:goTopBlock
- oTbrNew:headSep := oTbrOld:headSep
- oTbrNew:hitBottom := oTbrOld:hitBottom
- oTbrNew:hitTop := oTbrOld:hitTop
- oTbrNew:nBottom := oTbrOld:nBottom
- oTbrNew:nLeft := oTbrOld:nLeft
- oTbrNew:nRight := oTbrOld:nRight
- oTbrNew:nTop := oTbrOld:nTop
- oTbrNew:rowPos := oTbrOld:rowPos
- oTbrNew:skipBlock := oTbrOld:skipBlock
- oTbrNew:stable := oTbrOld:stable
-
- RETURN oTbrNew
-
-
- FUNCTION TBMsg(c)
-
- LOCAL cSs := saveScreen(maxRow(), 0, maxRow(), maxCol())
-
- @ maxRow(), 0
- @ maxRow(), 0 SAY c
- inkey(0)
-
- restScreen(maxRow(), 0, maxRow(), maxCol(), cSs)
-
- RETURN NIL
-
-
- FUNCTION StdMeth(nKey, oTbr)
-
- LOCAL lKeyHandled := .T.
-
- DO CASE
- CASE nKey == K_DOWN; oTbr:down()
- CASE nKey == K_UP; oTbr:up()
- CASE nKey == K_PGDN; oTbr:pageDown()
- CASE nKey == K_PGUP; oTbr:pageUp()
- CASE nKey == K_CTRL_PGUP; oTbr:goTop()
- CASE nKey == K_CTRL_PGDN; oTbr:goBottom()
- CASE nKey == K_RIGHT; oTbr:right()
- CASE nKey == K_LEFT; oTbr:left()
- CASE nKey == K_HOME; oTbr:home()
- CASE nKey == K_END; oTbr:end()
- CASE nKey == K_CTRL_LEFT; oTbr:panLeft()
- CASE nKey == K_CTRL_RIGHT; oTbr:panRight()
- CASE nKey == K_CTRL_HOME; oTbr:panHome()
- CASE nKey == K_CTRL_END; oTbr:panEnd()
- OTHERWISE; lKeyHandled := .F.
- ENDCASE
-
- RETURN lKeyHandled
-
-
- FUNCTION NumVisibleRows(oTbr)
-
- LOCAL nSaveRowPos := oTbr:rowPos
- LOCAL nLastVisible
-
- dispBegin()
- oTbr:deHilite()
-
- oTbr:rowPos := oTbr:rowCount
- DO WHILE !oTbr:stabilize()
- ENDDO
-
- nLastVisible := oTbr:rowPos
-
- oTbr:deHilite()
-
- oTbr:rowPos := nSaveRowPos
- DO WHILE !oTbr:stabilize()
- ENDDO
-
- dispEnd()
-
- RETURN nlastVisible
-
-
- FUNCTION TBCColPos(oTbr)
-
- LOCAL nSaveColNum := oTbr:colPos
- LOCAL aColPos := array(oTbr:rightVisible)
- LOCAL nColNum
-
- dispBegin()
- FOR nColNum := oTbr:leftVisible TO oTbr:rightVisible
- oTbr:colPos := nColNum
- DO WHILE !oTbr:stabilize()
- ENDDO
- aColPos[nColNum] := col()
- oTbr:deHilite()
- NEXT
-
- // redisplay current prompt
- oTbr:colPos := nSaveColNum
- DO WHILE !oTbr:stabilize()
- ENDDO
-
- dispEnd()
-
- RETURN aColPos
-
-
- FUNCTION TBForStart(bFor)
-
- GOTO TOP
- DO WHILE !eof() .AND. !eval(bFor)
- SKIP
- ENDDO
-
- // Already at eof() if !eval(bFor)
-
- RETURN NIL
-
-
- FUNCTION TBForEnd(bFor)
-
- GOTO BOTTOM
- DO WHILE !bof() .AND. !eval(bFor)
- SKIP -1
- ENDDO
-
- IF bof()
- // no records match filter
- GOTO 0
- ENDIF
-
- RETURN NIL
-
-
- FUNCTION TBForSkip(nToSkip, bFor)
-
- FIELD Lname IN TbDbf1
- LOCAL nSkipped := 0, ;
- nLastValidRecNum := Recno()
-
- IF nToSkip == 0
- SKIP 0
- RETURN 0
- ENDIF
-
- IF nToSkip > 0
- DO WHILE nSkipped < nToSkip .AND. !Eof()
- SKIP
- DO WHILE !eval(bFor) .AND. !Eof()
- SKIP
- ENDDO
- IF eval(bFor)
- nSkipped++
- nLastValidRecNum := Recno()
- ENDIF
- ENDDO
- IF eof()
- GOTO nLastValidRecNum
- ENDIF
- ELSE
- DO WHILE nSkipped > nToSkip .AND. !Bof()
- SKIP -1
- DO WHILE !eval(bFor) .AND. !Bof()
- SKIP -1
- ENDDO
- IF eval(bFor)
- nSkipped--
- nLastValidRecNum := Recno()
- ENDIF
- ENDDO
- IF Bof()
- GOTO nLastValidecNum
- ENDIF
- ENDIF
-
- RETURN nSkipped
-
-
- FUNCTION TBForWhile(bFirst, bLast, bFor, bWhile)
-
- LOCAL oTbr := TBrowseNew()
-
- oTbr:goTopBlock := {|| TBFwFirst(bFirst, bWhile, bFor) }
- oTbr:goBottomBlock := {|| TBFwLast(bLast, bWhile, bFor) }
- oTbr:skipBlock := {|n| TBFwSkip(n, bWhile, bFor) }
-
- RETURN oTbr
-
-
- FUNCTION TBFwFirst(bGoFirst, bWhile, bFor)
-
- eval(bGoFirst)
- DO WHILE !eof() .AND. eval(bWhile) .AND. !eval(bFor)
- SKIP
- ENDDO
-
- IF !eval(bWhile)
- // no records match filter - could also be at eof already here
- GOTO 0
- ENDIF
-
- RETURN NIL
-
-
- FUNCTION TBFwLast(bGoLast, bWhile, bFor)
-
- eval(bGoLast)
- DO WHILE !bof() .AND. eval(bWhile) .AND. !eval(bFor)
- SKIP -1
- ENDDO
-
- IF bof() .OR. !eval(bWhile)
- // No records match scope
- GOTO 0
- ENDIF
-
- RETURN NIL
-
-
- FUNCTION TBFwSkip(nToSkip, bWhile, bFor)
-
- LOCAL nSkipped := 0, ;
- nLastValidRecNum := Recno()
-
- IF nToSkip = 0
- SKIP 0
- RETURN 0
- ENDIF
-
- IF nToSkip > 0
- DO WHILE nSkipped < nToSkip .AND. !eof() .AND. eval(bWhile)
- SKIP
- // Note the last clause here makes a big speed difference
- DO WHILE !eval(bFor) .AND. !eof() .AND. eval(bWhile)
- SKIP
- ENDDO
- IF Eval(bWhile) .AND. !eof()
- // Found a new record matching the scope
- nSkipped++
- nLastValidRecNum := Recno()
- ENDIF
- ENDDO
-
- IF eof() .OR. !eval(bWhile)
- GOTO nLastValidRecNum
- ENDIF
- ELSE
- DO WHILE nSkipped > nToSkip .AND. !bof() .AND. eval(bWhile)
- SKIP -1
- // Note the last clause here makes a big speed difference
- DO WHILE !eval(bFor) .AND. !bof() .AND. eval(bWhile)
- SKIP -1
- ENDDO
- IF Eval(bWhile) .AND. !bof()
- nSkipped--
- nLastValidRecNum := Recno()
- ENDIF
- ENDDO
- IF !eval(bWhile) .OR. bof()
- GOTO nLastValidRecNum
- ENDIF
- ENDIF
-
- RETURN nSkipped
-
-
- FUNCTION AddAllFields(oTbr)
-
- LOCAL oTbc, ;
- nFieldNum, ;
- nFields := fcount(), ;
- temp
-
- FOR nFieldNum := 1 TO nFields
- IF valtype(fieldget(nFieldNum)) == "M"
- oTbc := TBColumnNew(field(nFieldNum), ;
- MemoBlock(nFieldNum))
- ELSE
- oTbc := TBColumnNew(field(nFieldNum), fieldblock(field(nFieldNum)))
- ENDIF
- oTbr:addColumn(oTbc)
- NEXT
-
- RETURN NIL
-
- FUNCTION MemoBlock(nFieldNum)
-
- RETURN {|nMode| iif(nMode == NIL, ;
- "Memo", ;
- fieldblock(field(nFieldNum))) }
-
-
- FUNCTION DbSkipBlock(n, bNext, bPrev)
-
- LOCAL nSkipped := 0
-
- // Idiosyncrasy for database skipper - probably unnec. actually
- IF n = 0
- SKIP 0
- ELSEIF n > 0
- DO WHILE nSkipped != n .AND. eval(bNext)
- nSkipped++
- ENDDO
- ELSE
- DO WHILE nSkipped != n .AND. eval(bPrev)
- nSkipped--
- ENDDO
- ENDIF
-
- RETURN nSkipped
-
-
- // Repeatedly call TBrowse:stabilize() until it returns .T.
-
- FUNCTION FullStabilize(oTbr)
-
- DO WHILE !oTbr:stabilize()
- ENDDO
-
- RETURN NIL
-
-
- // Repeatedly call TBrowse:stabilize() until it returns .T. OR the
- // user presses a key. Returns .T. if stabilized otherwise .F.
-
- FUNCTION KeyStabilize(oTbr)
-
- DO WHILE NextKey() == 0 .AND. !oTbr:stabilize()
- ENDDO
-
- RETURN oTbr:stable
-
-
- // Repeatedly call stabilize until it returns .T., ensuring the same
- // record is highlighted (for database edits)
-
- FUNCTION DbStabilize(oTbr)
-
- LOCAL nSaveRecno := recno()
-
- oTbr:refreshAll()
- FullStabilize(oTbr)
-
- DO WHILE recno() != nSaveRecno
- oTbr:up()
- FullStabilize(oTbr)
- ENDDO
-
- RETURN NIL
-
-
- // Tbrowse routine called by goTopBlock. fwa stands for
- // "for/while/append". It supports generic for and while
- // conditions and append mode.
-
- FUNCTION TBfwaFirst(bGoFirst, bWhile, bFor)
-
- eval(bGoFirst)
- DO WHILE !eof() .AND. eval(bWhile) .AND. !eval(bFor)
- SKIP
- ENDDO
-
- IF eof() .OR. !eval(bWhile)
- GOTO 0
- ENDIF
-
- RETURN NIL
-
-
- // Routine called by goBottomBlock to move to the last record
- // in the database matching the for and while condition, and
- // taking append mode into account.
-
- FUNCTION TBfwaLast(bGoLast, bWhile, bFor, lAppend)
-
- IF lAppend
- GOTO 0
- ELSE
- eval(bGoLast)
- DO WHILE !bof() .AND. eval(bWhile) .AND. !eval(bFor)
- SKIP -1
- ENDDO
-
- IF bof() .OR. !eval(bWhile)
- GOTO 0
- ENDIF
- ENDIF
-
- RETURN NIL
-
-
- // Move to next record supporting for and while conditions
- // and append mode
-
- FUNCTION TBfwaGoNext(bFor, bWhile, lAppend)
-
- LOCAL nSaveRecNum := recno()
- LOCAL lMoved := .T.
-
- IF eof()
- lMoved := .F.
- ELSE
- SKIP
- DO WHILE !eval(bFor) .AND. eval(bWhile) .AND. !eof()
- SKIP
- ENDDO
-
- IF eof() .AND. lAppend
- // fine ...
- ELSEIF !eval(bWhile) .OR. eof()
- IF !eval(bWhile) .AND. lAppend
- GOTO 0
- ELSE
- lMoved := .F.
- GOTO nSaveRecNum
- ENDIF
- ENDIF
- ENDIF
-
- RETURN lMoved
-
-
- // Move to previous record supporting for and while conditions
- // and append mode
-
- FUNCTION TBfwaGoPrev(bFor, bWhile, bLast)
-
- LOCAL nSaveRecNum := recno()
- LOCAL lMoved := .T.
-
- // Take special care at eof() - a SKIP -1 is not sufficient
- // because of the filters
- IF eof()
- eval(bLast)
- ELSE
- SKIP -1
- ENDIF
-
- DO WHILE !eval(bFor) .AND. eval(bWhile) .AND. !bof()
- SKIP -1
- ENDDO
-
- IF !eval(bWhile) .OR. bof()
- GOTO nSaveRecNum
- lMoved := .F.
- ENDIF
-
- RETURN lMoved
-
-
- // Creates and returns a TBrowse object for a browse with a while
- // and for condition and append mode
-
- FUNCTION TBfwaBrowse(bWhile, bFor, bFirst, bLast)
-
- LOCAL oTbr := TBrowseNew()
- LOCAL bNext := {|| TBfwaGoNext(bFor, bWhile, APPEND_MODE(oTbr)) }
- LOCAL bPrev := {|| TBfwaGoPrev(bFor, bWhile, bLast) }
-
- oTbr:cargo := DictNew()
- APPEND_MODE(oTbr, .F.)
-
- oTbr:goTopBlock := {|| TBfwaFirst(bFirst, bWhile, bFor) }
-
- oTbr:goBottomBlock := {|| TBfwaLast(bLast, bWhile, bFor, ;
- APPEND_MODE(oTbr)) }
- oTbr:skipBlock := {|n| DbSkipBlock(n, bNext, bPrev) }
-
- oTbr:goTop()
-
- RETURN oTbr
-
-
- FUNCTION TBWhStart(bFirst, bWhile)
-
- eval(bFirst)
- IF !eval(bWhile)
- GOTO 0
- ENDIF
-
- RETURN NIL
-
-
- FUNCTION TBWhEnd(bLast, bWhile)
-
- eval(bLast)
- IF !eval(bWhile)
- GOTO 0
- ENDIF
-
- RETURN NIL
-
-
- // Handles empty databases and no records matching condition
-
- FUNCTION TBWhSkip(nToSkip, bWhile)
-
- LOCAL nSkipped := 0
-
- IF nToSkip = 0
- SKIP 0
- RETURN 0
- ENDIF
-
- IF nToSkip > 0
- DO WHILE eval(bWhile) .AND. !eof() .AND. nSkipped < nToSkip
- SKIP
- IF eval(bWhile) .AND. !eof()
- nSkipped++
- ENDIF
- ENDDO
- IF !eval(bWhile) .OR. eof()
- SKIP -1
- ENDIF
- ELSE
- DO WHILE eval(bWhile) .AND. !bof() .AND. nSkipped > nToSkip
- SKIP -1
- IF eval(bWhile) .AND. !bof()
- nSkipped--
- ENDIF
- ENDDO
- IF !eval(bWhile)
- SKIP
- ENDIF
- ENDIF
-
- RETURN nSkipped
-
-
- FUNCTION TBFwGoNext(bFor, bWhile)
-
- LOCAL nSaveRecNum := recno()
- LOCAL lMoved := .T.
-
- SKIP
- DO WHILE !eval(bFor) .AND. eval(bWhile) .AND. !eof()
- SKIP
- ENDDO
-
- IF !eval(bWhile) .OR. eof()
- GOTO nSaveRecnum
- lMoved := .F.
- ENDIF
-
- RETURN lMoved
-
-
- FUNCTION TBFwGoPrev(bFor, bWhile)
-
- LOCAL nSaveRecNum := recno()
- LOCAL lMoved := .T.
-
- SKIP -1
- DO WHILE !eval(bFor) .AND. eval(bWhile) .AND. !bof()
- SKIP -1
- ENDDO
-
- IF !eval(bWhile) .OR. bof()
- GOTO nSaveRecNum
- lMoved := .F.
- ENDIF
-
- RETURN lMoved
-
-
- FUNCTION TBaGoPrev
-
- LOCAL lMoved := .T.
-
- SKIP -1
- IF bof()
- lMoved := .F.
- ENDIF
-
- RETURN lMoved
-
-
- FUNCTION TBaGoNext(lAppend)
-
- LOCAL lMoved := .T.
-
- IF eof() .OR. LastRec() = 0
- lMoved := .F.
- ELSE
- SKIP
- IF eof() .AND. !lAppend
- SKIP -1
- lMoved := .F.
- ENDIF
- ENDIF
-
- RETURN lMoved
-
-
- FUNCTION TBaGoFirst
-
- GOTO TOP
-
- RETURN NIL
-
-
- FUNCTION TBaGoLast(lAppend)
-
- GOTO BOTTOM
- IF lAppend
- SKIP
- ENDIF
-
- RETURN NIL
-