home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-04-14 | 19.9 KB | 1,044 lines |
- /***********
- * Program....: DBU
- * Filename...: DBUEDIT.PRG
- * Author.....: Dennis L. Dias
- * Date.......: 06/18/86, 06/18/90, 03/26/91
- * Purpose....: Data File Editing Module
- *
- * Copyright (c) 1986-1991 Nantucket Corp., All Rights Reserved.
- */
-
- #include "inkey.ch"
- #include "memoedit.ch"
-
-
- /***
- * browse
- *
- * browse one file or the entire View
- */
- proc browse
-
- local i,j,nHelpSave,cNtx,cFieldArray,cFieldName,nWa,cMemo,oB,nRec,;
- cBrowseBuf,nPrimeArea,nHsepRow,cEditField,bAlias,cAlias,nCType,;
- cHead,lMore,lCanAppend,cMemoBuff,aMoveExp,cPrimeDbf,;
- nColorSave,lAppend,lGotKey,lKillAppend,bColBlock
- memvar keystroke,help_code,func_sel,cur_area,cur_dbf,field_list,frame,;
- curs_on,cur_ntx,ntx1,dbf,local_func,box_open,;
- color1,color7,color8,color9
-
- /* turn off cursor */
- nCType := SetCursor(0)
- curs_on := .f.
-
- /* save prev help code */
- nHelpSave := help_code
-
- /* save, clear, and frame the window */
- cBrowseBuf := SaveScreen(8, 0, 23, 79)
-
- /* array to save move_ptr expressions */
- aMoveExp := Array(4)
- AFill(aMoveExp, "")
-
- /* heading separator row if only one database */
- nHsepRow := 11
-
- /* determine what to browse */
- if ( func_sel == 1 )
- /* browse one file */
- nPrimeArea := cur_area
- cFieldArray := "field_n" + Substr("123456", cur_area, 1)
- cNtx := "ntx" + Substr("123456", cur_area, 1)
- cur_ntx := &cNtx[1]
- cPrimeDbf := Substr(cur_dbf, Rat("\", cur_dbf) + 1)
- lCanAppend := .T.
- else
- /* browse the entire view */
- nPrimeArea := 1
- cFieldArray := "field_list"
- cur_ntx := ntx1[1]
- cPrimeDbf := Substr(dbf[1], Rat("\", dbf[1]) + 1)
- lCanAppend := .F.
-
- if ( "->" $ field_list[afull(field_list)] )
- nHsepRow := 12
- end
- end
-
- /* block to extract alias from alias->field */
- bAlias := &("{|i| if('->' $" + cFieldArray + "[i], Substr(" +;
- cFieldArray + "[i], 1, At('->'," + cFieldArray +;
- "[i]) - 1), '')}")
-
- Select(nPrimeArea)
- if ( Eof() )
- /* end of file not allowed */
- go top
- end
-
- /* misc */
- lAppend := .F.
- nRec := 0
-
- /* create TBrowse object */
- nColorSave := SetColor(color7)
- oB := TBrowseDB(10, 1, 23, 78)
-
- oB:headSep := "═╤═"
- oB:colSep := " │ "
- oB:footSep := "═╧═"
- oB:skipBlock := {|x| Skipped(x, lAppend)}
-
- /* put columns into browse */
- j := Len(&cFieldArray)
- for i := 1 TO j
- if ( Empty(&cFieldArray[i]) )
- EXIT
- end
-
- /* determine workarea/alias stuff */
- cEditField := &cFieldArray[i]
- if ( "->" $ cEditField )
- cAlias := Substr(cEditField, 1, At("->", cEditField) + 1)
- cFieldName := Substr(cEditField, At("->", cEditField) + 2)
- cHead := cAlias + ";" + cFieldName
- nWa := Select(cAlias)
- else
- cAlias := ""
- cFieldName := cHead := cEditField
- nWa := Select()
- end
-
- /* memos are handled differently */
- if ( ValType(&cEditField) == "M" )
- bColBlock := &("{|| ' <Memo> '}")
- else
- bColBlock := FieldWBlock(cFieldName, nWa)
- end
-
- /* add one column */
- oB:addColumn(TBColumnNew(cHead, bColBlock))
- next
-
- /* initialize parts of screen not handled by TBrowse */
- stat_msg("")
- scroll(8, 0, 23, 79, 0)
- @ 8, 0, 23, 79 BOX frame
- @ nHsepRow, 0 SAY "╞"
- @ nHsepRow, 79 SAY "╡"
-
- /* init rest of locals */
- cAlias := ""
- lKillAppend := .f.
- if ( (LastRec() == 0) .and. lCanAppend )
- /* empty file..force append mode */
- keystroke := K_DOWN
- lGotKey := .t.
- else
- lGotKey := .f.
- end
-
- lMore := .t.
- while (lMore)
- if ( !lGotKey )
- /* keystroke will interrupt stabilize */
- while ( !oB:stabilize() )
- if ( (keystroke := Inkey()) != 0 )
- lGotKey := .t.
- exit
- end
- end
- end
-
- if ( !lGotKey )
- if ( oB:hitBottom .and. lCanAppend )
- /* turn on or continue append mode */
- if ( !lAppend .or. Recno() != LastRec() + 1 )
- if ( lAppend )
- /* continue append mode */
- oB:refreshCurrent()
- while ( !oB:stabilize() ) ; end
- go bottom
- else
- /* first append */
- lAppend := .t.
- SetCursor(1)
- curs_on := .t.
- end
-
- /* move down and stabilize to set rowPos */
- oB:down()
- while ( !oB:stabilize() ) ; end
- oB:colorRect({oB:rowPos,1,oB:rowPos,oB:colCount},{2,2})
- end
- end
-
- /* display status */
- cAlias := Eval(bAlias, oB:colPos)
- statline(oB, lAppend, cAlias)
-
- /* stabilize again for correct cursor pos */
- while ( !oB:stabilize() ) ; end
-
- /* idle */
- keystroke := Inkey(0)
- else
- /* reset for next loop */
- lGotKey := .f.
- end
-
- do case
- case keystroke == K_DOWN
- if ( lAppend )
- oB:hitBottom := .t.
- else
- oB:down()
- end
-
- case keystroke == K_UP
- if ( lAppend )
- lKillAppend := .t.
- else
- oB:up()
- end
-
- case keystroke == K_PGDN
- if ( lAppend )
- oB:hitBottom := .t.
- else
- oB:pageDown()
- end
-
- case keystroke == K_PGUP
- if ( lAppend )
- lKillAppend := .t.
- else
- oB:pageUp()
- end
-
- case keystroke == K_CTRL_PGUP
- if ( lAppend )
- lKillAppend := .t.
- else
- oB:goTop()
- end
-
- case keystroke == K_CTRL_PGDN
- if ( lAppend )
- lKillAppend := .t.
- else
- oB:goBottom()
- end
-
- case keystroke == K_RIGHT
- oB:right()
-
- case keystroke == K_LEFT
- oB:left()
-
- case keystroke == K_HOME
- oB:home()
-
- case keystroke == K_END
- oB:end()
-
- case keystroke == K_CTRL_LEFT
- oB:panLeft()
-
- case keystroke == K_CTRL_RIGHT
- oB:panRight()
-
- case keystroke == K_CTRL_HOME
- oB:panHome()
-
- case keystroke == K_CTRL_END
- oB:panEnd()
-
- case keystroke == K_DEL
- /* toggle deleted() flag */
- while ( !oB:stabilize() ) ; end
- cAlias := Eval(bAlias, oB:colPos)
- if ( !Empty(cAlias) )
- Select(cAlias)
- end
-
- if ( Recno() != Lastrec() + 1 )
- if Deleted()
- recall
- else
- delete
- end
- end
-
- Select(nPrimeArea)
-
- case keystroke == K_INS
- /*toggle insert mode */
- tog_insert()
-
- case keystroke == K_RETURN
- /* edit the current field */
- while ( !oB:stabilize() ) ; end
- cAlias := Eval(bAlias, oB:colPos)
-
- if ( !Empty(cAlias) )
- Select(cAlias)
- end
-
- if ( !lAppend .and. (Recno() == LastRec() + 1) )
- Select(nPrimeArea)
- loop /* NOTE */
- end
-
- Select(nPrimeArea)
-
- /* make sure the display is correct */
- oB:hitTop := .f.
- Statline(oB, lAppend, cAlias)
- while ( !oB:stabilize() ) ; end
-
- cEditField := &cFieldArray[oB:colPos]
-
- /* turn the cursor on */
- SetCursor(1)
- curs_on := .t.
-
- if ( Type(cEditField) == "M" )
- /* edit memo field */
- help_code := 19
- box_open := .t.
-
- /* save, clear, and frame window for memoedit */
- cMemoBuff := SaveScreen(10, 10, 22, 69)
-
- SetColor(color8)
- Scroll(10, 10, 22, 69, 0)
- @ 10, 10, 22, 69 BOX frame
-
- /* use fieldspec for title */
- SetColor(color9)
- @ 10,((76 - Len(cEditField)) / 2) SAY " " + cEditField + " "
-
- /* edit the memo field */
- SetColor(color8)
- cMemo := MemoEdit(&cEditField, 11, 11, 21, 68,.T.,"xmemo")
-
- if Lastkey() == K_CTRL_END
- /* ^W..new memo confirmed */
-
- if ( lAppend .and. Eof() )
- /* first data in new record */
- append blank
- end
-
- /* put it there */
- replace &cEditField WITH cMemo
- oB:refreshCurrent()
-
- /* move to next field */
- keystroke := K_RIGHT
- lGotKey := .t.
- else
- keystroke := 0
- end
-
- /* restore the window */
- RestScreen(10, 10, 22, 69, cMemoBuff)
- box_open := .F.
- else
- /* regular data entry */
- SetColor(color1)
- keystroke := DoGet(oB, lAppend, cAlias)
- lGotKey := ( keystroke != 0 )
- end
-
- /* turn off the cursor unless append mode */
- if ( !lAppend )
- SetCursor(0)
- curs_on := .f.
- end
-
- help_code := nHelpSave
- SetColor(color7)
-
- otherwise
- if ( isdata(keystroke) )
- /* forward data keystroke to GET system */
- keyboard Chr(K_RETURN) + Chr(keystroke)
- else
- /* check for menu request */
- sysmenu()
-
- do case
- case q_check()
- /* exit */
- lMore := .f.
-
- case local_func == 1
- /* help requested */
- DO syshelp
-
- case local_func == 7
- /* move option selected..only the primary can be moved */
- nRec := Recno()
- move_ptr(aMoveExp, cPrimeDbf)
-
- if ( nRec != Recno() )
- if ( lAppend )
- /* no more append mode */
- lKillAppend := .t.
- else
- FreshOrder(oB)
- end
- end
- end
- end
- end
-
- if ( lKillAppend )
- /* turn off append mode */
- lKillAppend := .f.
- lAppend := .f.
-
- /* refresh respecting any change in index order */
- FreshOrder(oB)
- SetCursor(0)
- curs_on := .f.
- end
- end
-
- /* restore the screen */
- RestScreen(8, 0, 23, 79, cBrowseBuf)
- SetColor(nColorSave)
- SetCursor(nCType)
- curs_on := (nCType != 0)
- stat_msg("")
-
- return
-
-
- /***
- * xmemo()
- *
- * memoedit user function
- */
- func xmemo(mmode, line, col)
- local nRet
- memvar keystroke,local_func
-
- nRet := 0
-
- if mmode <> ME_IDLE
- /* check for menu request */
- keystroke := Lastkey()
- sysmenu()
-
- do case
- case local_func == 1
- /* help requested */
- do syshelp
-
- case keystroke == K_INS
- /* insert key pressed */
- tog_insert()
- nRet := ME_IGNORE
-
- case keystroke == K_ESC
- /* escape key pressed */
- if mmode == ME_UNKEYX
- /* memo has been altered */
- if rsvp("Ok To Lose Changes? (Y/N)") <> "Y"
- /* no exit if not confirmed (32 == ignore) */
- nRet := ME_IGNORE
- end
- end
- end
- end
-
- return (nRet)
-
-
- /***
- * tog_insert()
- *
- * ditto
- */
- static func tog_insert
- local nCType
-
- Readinsert(!Readinsert())
- nCType := SetCursor(0)
- show_insert()
- SetCursor(nCType)
-
- return (0)
-
-
- /***
- * show_insert()
- *
- * display current insert mode
- */
- static func show_insert
- local nColorSave
-
- nColorSave := SetColor(color7)
- @ 9,4 say if(ReadInsert(), "<Insert>", " ")
- SetColor(nColorSave)
-
- return (0)
-
-
- /***
- * statline()
- *
- * update the status line in the browse window
- */
- static func statline(oB, lAppend, cAlias)
- local cColorSave, cCurrAlias, lNoFilter, nWaSave, nCType
-
- /* preserve current state */
- nCType := SetCursor(0)
-
- nWaSave := Select()
- if ( !Empty(cAlias) )
- Select(cAlias)
- end
-
- cColorSave := SetColor(color7)
-
- /* show current mode */
- show_insert()
-
- /* show filter status */
- lNoFilter := Empty(&("kf" + Substr("123456", Select(), 1)))
- @ 9,16 say if(lNoFilter, " ", "<Filter>")
-
- /* display record pointer information */
- @ 9,41 say if(Empty(cAlias), space(10), Lpad(cAlias + "->", 10));
- + "Record "
-
- if ( EmptyFile() .and. .not. lAppend )
- /* file is empty */
- @ 9,58 say "<none> "
- elseif ( Eof() )
- /* no record number if eof */
- @ 9,28 say " "
- @ 9,58 say " " + if(lAppend, "<new>", "<eof>")
- else
- /* normal record..display recno()/lastrec() and deleted() */
- @ 9,28 say if(Deleted(), "<Deleted>", " ")
- @ 9,58 say Pad(Ltrim(Str(Recno())) + "/" + Ltrim(Str(Lastrec())),15)+;
- If(oB:hitTop, " <bof>", if(oB:hitBottom, " <eof>", " "))
- end
-
- /* restore state */
- SetColor(cColorSave)
- Select(nWaSave)
- SetCursor(nCType)
-
- return (0)
-
-
- /***
- * move_ptr()
- *
- * seek, goto, locate, skip
- *
- * the following array is defined and initialized in browse:
- * aMoveExp[1] == the last SEEK expression
- * aMoveExp[2] == the last GOTO value
- * aMoveExp[3] == the last LOCATE expressions
- * aMoveExp[4] == the last SKIP value
- */
- static func move_ptr(aMoveExp, cPrimeDbf)
-
- local nHelpSave,aBox
- memvar okee_dokee, k_trim, movp_sel, titl_str, exp_label
- memvar help_code,local_sel,ntx_expr
- private okee_dokee, k_trim, movp_sel, titl_str, exp_label, ntx_expr
-
- nHelpSave := help_code
-
- /* save function select number */
- movp_sel := local_sel
-
- /* initialize expression to previous value, if any */
- k_trim := aMoveExp[movp_sel]
-
- /* set up for multibox */
- aBox := Array(4)
-
- aBox[1] := "movp_title(sysparam)"
- aBox[2] := "movp_exp(sysparam)"
- aBox[3] := "ok_button(sysparam)"
- aBox[4] := "can_button(sysparam)"
-
- do case
- case movp_sel == 1
- /* seek */
- okee_dokee := "do_seek()"
- titl_str := "Seek in file " + cPrimeDbf + "..."
- exp_label := "Expression"
- ntx_expr := Indexkey(0)
- help_code := 13
-
- case movp_sel == 2
- /* goto */
- okee_dokee := "do_goto()"
- titl_str := "Move pointer in file " + cPrimeDbf + " to..."
- exp_label := "Record#"
- help_code := 14
-
- case movp_sel == 3
- /* locate */
- okee_dokee := "do_locate()"
- titl_str := "Locate in file " + cPrimeDbf + "..."
- exp_label := "Expression"
- help_code := 10
-
- case movp_sel == 4
- /* skip */
- okee_dokee := "do_skip()"
- titl_str := "Skip records in file " + cPrimeDbf + "..."
- exp_label := "Number"
- help_code := 20
- end
-
- /* do it */
- set key K_INS to tog_insert
- multibox(14, 17, 5, 2, aBox)
- set key K_INS to
-
- /* save expression for next time */
- aMoveExp[movp_sel] := k_trim
-
- help_code := nHelpSave
-
- return (0)
-
-
- /***
- * movp_title()
- *
- * display title for move pointer functions
- */
- func movp_title(sysparam)
- memvar titl_str
- return (box_title(sysparam, titl_str))
-
-
- /***
- * movp_exp()
- *
- * get parameter for move pointer
- */
- func movp_exp(sysparam)
- memvar exp_label
- return (get_k_trim(sysparam, exp_label))
-
-
- /***
- * do_seek()
- *
- * seek to expression
- */
- func do_seek
-
- local lDone, nRec, cSeekType
- memvar k_trim,ntx_expr
-
- lDone := .F.
-
- if Empty(k_trim)
- error_msg("Expression not entered")
- else
- stat_msg("Searching...")
-
- /* save record number in case no find */
- nRec := Recno()
-
- /* determine type for seek */
- cSeekType := Type(ntx_expr)
-
- /* try it */
- do case
- case cSeekType == "C"
- /* character search */
- seek k_trim
-
- case cSeekType == "N"
- /* numeric search */
- seek Val(k_trim)
-
- case cSeekType == "D"
- /* date search */
- seek Ctod(k_trim)
- end
-
- if Found()
- /* operation complete */
- stat_msg("Found")
- lDone := .T.
- else
- /* consider this an error..start over */
- error_msg("Not found")
- goto nRec
- end
- end
-
- return (lDone)
-
-
- /***
- * do_goto()
- *
- * go to record number
- */
- func do_goto
-
- local lDone, nWhich
- memvar k_trim
-
- lDone := .F.
- nWhich := Val(k_trim) && convert to number
-
- do case
- case Empty(k_trim)
- error_msg("Record number not entered")
-
- case .not. Substr(Ltrim(k_trim), 1, 1) $ "-+1234567890"
- error_msg("Record number not numeric")
-
- case nWhich <= 0 .or. nWhich > Lastrec()
- error_msg("Record out of range")
-
- otherwise
- /* operation complete */
- goto nWhich
- lDone := .T.
-
- end
-
- return (lDone)
-
-
- /***
- * do_locate()
- *
- * locate expression
- */
- func do_locate
-
- local lDone, nRec
- memvar k_trim
-
- lDone := .F.
-
- do case
- case Empty(k_trim)
- error_msg("Expression not entered")
-
- case Type(k_trim) <> "L"
- error_msg("Expression Type must be Logical")
-
- otherwise
- /* save record number in case no find */
- nRec := Recno()
- stat_msg("Searching...")
-
- if &k_trim
- /* current record meets the condition */
- skip
- end
-
- /* search forward to end of file */
- locate for &k_trim while .T.
-
- if Found()
- /* operation complete */
- stat_msg("Found")
- lDone := .T.
-
- else
- /* consider this an error..start over */
- error_msg("Not found")
- goto nRec
- end
- end
-
- return (lDone)
-
-
- /***
- * do_skip()
- *
- * skip number of records
- */
- func do_skip
-
- local lDone, nSkip
- memvar k_trim
-
- lDone := .F.
- nSkip := Val(k_trim) && convert to number
-
- do case
- case Empty(k_trim)
- error_msg("Skip value not entered")
-
- case .not. Substr(Ltrim(k_trim), 1, 1) $ "-+1234567890"
- error_msg("Skip value not numeric")
-
- case nSkip == 0
- error_msg("Skip value zero")
-
- otherwise
- /* no out of range or over-skip error */
- lDone := .T.
-
- skip nSkip
-
- if Eof()
- /* over-skip..clear eof flag */
- go bottom
- end
-
- if Bof()
- /* over-skip..clear bof flag */
- go top
- end
- end
-
- return (lDone)
-
-
- /***
- * EmptyFile()
- */
-
- static func EmptyFile()
-
- if (LastRec() == 0 )
- return (.t.)
- end
-
- if ( (Eof() .or. Recno() == LastRec() + 1) .and. Bof() )
- return (.t.)
- end
-
- return (.f.)
-
-
- /***
- * DoGet()
- *
- * Edit the current field
- */
-
- static func DoGet(oB, lAppend, cAlias)
-
- local lExitSave, oCol, oGet, nKey, cExpr, xEval
- local lFresh, mGetVar, nWaSave
-
- /* save state */
- lExitSave := Set(_SET_EXIT, .t.)
- nWaSave := Select()
- if ( !Empty(cAlias) )
- Select(cAlias)
- end
-
- /* set insert key to toggle insert mode and cursor */
- set key K_INS to tog_insert
- xkey_clear()
-
- /* get the controlling index key */
- cExpr := IndexKey(0)
- if ( !Empty(cExpr) )
- /* expand key expression for later comparison */
- xEval := &cExpr
- end
-
- /* get column object from browse */
- oCol := oB:getColumn(oB:colPos)
-
- /* use temp for safety */
- mGetVar := Eval(oCol:block)
-
- /* create a corresponding GET with ambiguous set/get block */
- oGet := GetNew(Row(), Col(), ;
- {|x| if(PCount() == 0, mGetVar, mGetVar := x)}, ;
- "mGetVar")
-
- /* refresh flag */
- lFresh := .f.
-
- /* read it */
- if ( ReadModal( {oGet} ) )
- /* new data has been entered */
- if ( lAppend .and. Recno() == LastRec() + 1 )
- /* new record confirmed */
- append blank
- end
-
- /* replace with new data */
- Eval(oCol:block, mGetVar)
-
- /* test for change in index order */
- if ( !Empty(cExpr) .and. !lAppend )
- if ( xEval != &cExpr )
- /* change in index key eval */
- lFresh := .t.
- end
- end
- end
-
- Select(nWaSave)
- if ( lFresh )
- /* record in new indexed order */
- FreshOrder(oB)
-
- /* no other action */
- nKey := 0
- else
- /* refresh the current row only */
- oB:refreshCurrent()
-
- /* certain keys move cursor after edit if no refresh */
- nKey := ExitKey(lAppend)
- end
-
- if ( lAppend )
- /* maintain special row color */
- oB:colorRect({oB:rowPos,1,oB:rowPos,oB:colCount}, {2,2})
- end
-
- /* restore state */
- Set(_SET_EXIT, lExitSave)
- set key K_INS to
- xkey_norm()
-
- return (nKey)
-
-
- /***
- * ExitKey()
- *
- * Determine the follow-up action after editing a field
- */
-
- static func ExitKey(lAppend)
-
- memvar keystroke
-
- keystroke := LastKey()
- if ( keystroke == K_PGDN )
- /* move down if not append mode */
- if ( lAppend )
- keystroke := 0
- else
- keystroke := K_DOWN
- end
-
- elseif ( keystroke == K_PGUP )
- /* move up if not append mode */
- if ( lAppend )
- keystroke := 0
- else
- keystroke := K_UP
- end
-
- elseif ( keystroke == K_RETURN .or. isdata(keystroke) )
- /* return key or type out..move right */
- keystroke := K_RIGHT
-
- elseif (keystroke != K_UP .and. keystroke != K_DOWN .and. menu_key() == 0)
- /* no other action */
- keystroke := 0
- end
-
- return (keystroke)
-
-
- /***
- * FreshOrder()
- *
- * Refresh respecting any change in index order
- */
-
- static func FreshOrder(oB)
-
- local nRec
-
- nRec := Recno()
- oB:refreshAll()
-
- /* stabilize to see if TBrowse moves the record pointer */
- while ( !oB:stabilize() ) ; end
-
- if ( nRec != LastRec() + 1 )
- /* record pointer may move if bof is on screen */
- while ( Recno() != nRec )
- /* falls through unless record is closer to bof than before */
- oB:up()
- while ( !oB:stabilize() ) ; end
- end
- end
-
- return (NIL)
-
-
- /***
- * Skipped(n)
- *
- * Skip thru database and return the
- * actual number of records skipped
- */
-
- static func Skipped(nRequest, lAppend)
-
- local nCount
-
- nCount := 0
- if ( LastRec() != 0 )
- if ( nRequest == 0 )
- skip 0
-
- elseif ( nRequest > 0 .and. Recno() != LastRec() + 1 )
- /* forward */
- while ( nCount < nRequest )
- skip 1
- if ( Eof() )
- if ( lAppend )
- /* eof record allowed if append mode */
- nCount++
- else
- /* back to last actual record */
- skip -1
- end
-
- exit
- end
-
- nCount++
- end
-
- elseif ( nRequest < 0 )
- /* backward */
- while ( nCount > nRequest )
- skip -1
- if ( Bof() )
- exit
- end
-
- nCount--
- end
- end
- end
-
- return (nCount)
-
-
- /* eof dbuedit.prg */