home *** CD-ROM | disk | FTP | other *** search
- // Tb18.prg - Demonstrate editing and appending records during tbrowse
- // display. Append mode is indicated by an entry in the object's
- // cargo instance variable. Also have a for a while scope set. Handles
- // empty scopes and empty databases as well.
-
- // Compile with /a /m /n /w
- // Link with tbutils, dict
-
- #include "Inkey.ch"
- #include "Setcurs.ch"
- #include "Tbutils.ch"
-
- #define MOVE_UP_KEY(nKey) chr(nKey) $ (chr(K_UP) + chr(K_PGUP) + chr(K_CTRL_PGUP))
-
- MEMVAR getList
-
- FUNCTION Tb18
-
- FIELD Lname, Fname, Addr1, Addr2, Addr3, AcBal IN Tbdbf1
-
- LOCAL oTbr
- LOCAL lExitRequested := .F.
- LOCAL nKey
- LOCAL nSr, nSc
- LOCAL bWhile := {|| Upper(Lname) = "SPENCE" }
- LOCAL bFor := {|| AcBal > 0 }
- LOCAL bFirst := {|| DbSeek("SPENCE") }
- LOCAL bLast := {|| DbSeek("SPENCF", .T.), DbSkip(-1) }
- LOCAL bNext
- LOCAL bPrev
-
- Set(_SET_SCOREBOARD, .F.)
- Set(_SET_CURSOR, SC_NONE)
-
- USE Tbdbf1
- IF !File("Tbdbf1.ntx")
- INDEX ON upper(Lname + Fname) TO Tbdbf1
- ELSE
- SET INDEX TO Tbdbf1
- ENDIF
-
- CLEAR SCREEN
- @ 0, 0 TO 23, 79
-
- oTbr := TbrowseDb(1, 1, 22, 78)
-
- oTbr:addColumn(TBColumnNew("Rec #", {|| Recno() } ))
-
- oTbr:freeze := 1
- oTbr:cargo := DictNew()
-
- APPEND_MODE(oTbr, .F.)
- // Add next line for automatic append mode
- // APPEND_MODE(oTbr, .T.)
-
- oTbr:addColumn(TBColumnNew("Last Name", FieldBlock("Lname")))
- oTbr:addColumn(TBColumnNew("First Name", FieldBlock("Fname")))
- oTbr:addColumn(TBColumnNew("AcBal", FieldBlock("AcBal")))
-
- oTbr:goTopBlock := {|| TBfwaFirst(bFirst, bWhile, bFor) }
-
- oTbr:goBottomBlock := {|| TBfwaLast(bLast, bWhile, bFor, ;
- APPEND_MODE(oTbr)) }
-
- bNext := {|| TBfwaGoNext(bFor, bWhile, APPEND_MODE(oTbr)) }
- bPrev := {|| TBfwaGoPrev(bFor, bWhile, bLast) }
-
- oTbr:skipBlock := {|n| DbSkipBlock(n, bNext, bPrev) }
-
- oTbr:goTop()
-
- DO WHILE !lExitRequested
- FullStabilize(oTbr)
-
- IF oTbr:hitBottom .AND. !APPEND_MODE(oTbr) .AND. ;
- Alert("Add record", {"Yes", "No"}) = 1
-
- APPEND_MODE(oTbr, .T.)
- oTbr:goBottom()
- FullStabilize(oTbr)
- ELSEIF (Eof() .OR. LastRec() = 0) .AND. !APPEND_MODE(oTbr)
- // No records in database or none matching scope
- IF Alert("Add record", {"Yes", "No"}) = 1
- APPEND_MODE(oTbr, .T.)
- oTbr:down()
- FullStabilize(oTbr)
- ELSE
- lExitRequested := .T.
- ENDIF
- ENDIF
-
- nSr := Row()
- nSc := Col()
- @ 24, 0 SAY iif(APPEND_MODE(oTbr), "Appending", " ")
- @ nSr, nSc SAY ""
-
- IF !lExitRequested
- nKey := InKey(0)
- IF nKey == K_ESC
- // Special case Escape if we are appending
- IF APPEND_MODE(oTbr) .AND. LastRec() != 0
- APPEND_MODE(oTbr, .F.)
- oTbr:refreshAll()
- ELSE
- lExitRequested := .T.
- ENDIF
- ELSE
- KeyHandle(nKey, oTbr, bWhile, bFor, )
- ENDIF
- ENDIF
-
- ENDDO
-
- CLEAR SCREEN
-
- RETURN NIL
-
-
- FUNCTION FldEdit(oTbr, bWhile, bFor)
-
- LOCAL bFldGsb, cFval, lSaveCurs
- LOCAL cNewKeyVal, cOldKeyVal
- LOCAL aCols := TbcColPos(oTbr)
- LOCAL aFvals := array(oTbr:rightVisible)
- LOCAL i, lMemoUpdated := .F.
- LOCAL cMemoDisplay := "Memo"
- LOCAL aMemoVals := {}
- LOCAL nMemoNum
-
- nMemoNum := 0 // How many memos we've had so far
- FOR i := oTbr:leftVisible TO oTbr:rightVisible
- // tbColumn's block instance var is a get / set block
- bFldGsb := oTbr:getColumn(i):block
-
- // Get its contents to check whether really a memo ...
- aFvals[i] := Eval(bFldGsb)
- IF valtype(aFvals[i]) == "C" .AND. aFvals[i] == "Memo"
- // Evaluating bFldGsb with ANY parameter returns a get / set
- // block for memos
- bFldGsb := Eval(bFldGsb, .T.)
-
- // Evaluate this once to get the memo's contents and store in
- // aMemoVals array
- aadd(aMemoVals, Eval(bFldGsb))
-
- // Increment memo count
- nMemoNum++
-
- // Issue a GET on the string "Memo". Pass it the array containing
- // the memos and set the get object's cargo instance variable
- // to the index. The function can then access this subscript with
- // GetActive():cargo.
- @ Row(), aCols[i] GET cMemoDisplay ;
- WHEN MemoFunc(@lMemoUpdated, aMemoVals)
-
- GetList[len(GetList)]:cargo := nMemoNum
-
- ELSE
- @ Row(), aCols[i] GET aFvals[i]
- ENDIF
-
- NEXT
-
- // We must save old index key val to see whether
- // it changed after the edit
- cOldKeyVal := &(IndexKey())
-
- lSaveCurs := Set(_SET_CURSOR, SC_NORMAL)
- READ
- Set(_SET_CURSOR, lSaveCurs)
-
- IF (Updated() .OR. lMemoUpdated) .AND. LastKey() != K_ESC
- IF eof()
- APPEND BLANK
- DO WHILE NetErr()
- APPEND BLANK
- ENDDO
- ELSE
- DO WHILE !rlock()
- ENDDO
- ENDIF
-
- // Update all fields
- nMemoNum := 0
- FOR i := oTbr:leftVisible TO oTbr:rightVisible
- // tbColumn's block instance var is a get / set block
- bFldGsb := oTbr:getColumn(i):block
- cFval := Eval(bFldGsb);
-
- // Special handling for memos
- IF ValType(cFval) == "C" .AND. cFval == "Memo"
- nMemoNum++
-
- // Evaluating this with ANY parameter returns a get / set
- // block for the memo field
- bFldGsb := Eval(bFldGsb, .T.)
-
- // Now update the memo field to what we saved in the array
- Eval(bFldGsb, aMemoVals[nMemoNum])
- ELSE
- // Update the field
- Eval(bFldGsb, aFvals[i])
- ENDIF
- NEXT
-
- UNLOCK
-
- // First check to see whether current record still
- // satisfies the filter condition
- IF !Eval(bWhile) .OR. !Eval(bFor)
- // The current record is no longer in scope.
- // Move back to the first record in the scope
- APPEND_MODE(oTbr, .F.)
- oTbr:refreshAll()
- oTbr:goTop()
- ELSE
- // Get new key value - If you already have a code block
- // on the current index key, simply eval it here instead
- cNewKeyVal := &(IndexKey())
- // If the key changed, refreshAll()
- IF cOldKeyVal != cNewKeyVal .OR. APPEND_MODE(oTbr)
- IF APPEND_MODE(oTbr)
- APPEND_MODE(oTbr, .F.)
- ENDIF
- DbStabilize(oTbr)
- ELSE
- oTbr:refreshcurrent()
- ENDIF
- ENDIF
- ELSE // !updated()
- // To remove reverse video from gets
- oTbr:refreshCurrent()
- ENDIF
-
- RETURN .F.
-
-
- #define MEMO_TOP 10
- #define MEMO_LEFT 20
- #define MEMO_BOTTOM 20
- #define MEMO_RIGHT 60
-
- // Edit memo field. lMemoUpdated is passed by reference. Set it .T.
- // if this memo was updated, otherwise do not change it. aMemoVals
- // contains a reference to the array containing the memo fields' values
-
- FUNCTION MemoFunc(lMemoUpdated, aMemoVals)
-
- LOCAL cSaveScr, cFval
- LOCAL lThisMemoUpdated
-
- cSaveScr := savescreen(MEMO_TOP, MEMO_LEFT, ;
- MEMO_BOTTOM, MEMO_RIGHT)
- @ MEMO_TOP, MEMO_LEFT TO ;
- MEMO_BOTTOM, MEMO_RIGHT
- cFval := MemoEdit(aMemoVals[GetActive():cargo], ;
- MEMO_TOP + 1, MEMO_LEFT + 1, ;
- MEMO_BOTTOM - 1, MEMO_RIGHT - 1)
- lThisMemoUpdated := lastkey() == K_CTRL_W
- RestScreen(MEMO_TOP, MEMO_LEFT, MEMO_BOTTOM, ;
- MEMO_RIGHT, cSaveScr)
-
- IF lThisMemoUpdated
- // This updates the array element, but not the field. This is
- // done later.
- aMemoVals[GetActive():cargo] := cFval
- lMemoUpdated := .T.
- ENDIF
-
- RETURN .F.
-
-
- FUNCTION KeyHandle(nKey, oTbr, bWhile, bFor)
-
- IF StdMeth(nKey, oTbr)
- // Processed key as standard key
- IF MOVE_UP_KEY(nKey) .AND. APPEND_MODE(oTbr) .AND. LastRec() != 0
- APPEND_MODE(oTbr, .F.)
- oTbr:refreshAll()
- ENDIF
- ELSE
- DO CASE
- CASE nKey == K_ENTER // EDIT key
- IF oTbr:stable
- FldEdit(oTbr, bWhile, bFor)
- ENDIF
-
- CASE nKey == K_INS
- APPEND_MODE(oTbr, .T.)
- oTbr:goBottom()
-
- CASE nKey >= 32 .AND. nKey <= 255
- IF oTbr:stable
- KEYBOARD chr(K_ENTER) + chr(nKey)
- ENDIF
-
- ENDCASE
- ENDIF
-
- RETURN NIL