home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
PROGRAM
/
CLIPPER
/
DBI101
/
DBINS101.PRG
next >
Wrap
Text File
|
1993-02-07
|
7KB
|
280 lines
/*
* File......: DBINSERT.PRG
* Author....: Todd C. MacDonald
* CIS ID....: 73767,2242
* Date......: $Date$
* Revision..: $Revision$
* Log file..: $Logfile$
*
* This is an original work by Todd C. MacDonald and is hereby
* placed in the public domain.
*
* Modification history:
* ---------------------
*
* $Log$
*
*/
/* $DOC$
* $FUNCNAME$
* ft_dbins()
* $CATEGORY$
* To be assigned
* $ONELINER$
* Insert a blank record after (or before) the current record.
* $SYNTAX$
* ft_dbins( [<lBefore>] ) -> NIL
* $ARGUMENTS$
* <lBefore> set to .t. will cause the blank record to be
* inserted BEFORE the current record. If <lBefore> is .f.,
* or is not passed, the blank record is inserted AFTER the
* current record.
* $RETURNS$
* NIL
* $DESCRIPTION$
* This function physically inserts a new blank record after
* (or optionally before) the current record in the currently
* selected work area. It provides the functional equivalent
* of dBASE's INSERT [BEFORE] BLANK command.
*
* Caveats:
*
* ■ This function is not network compatible. The file on
* which you perform the insert must be USEed EXCLUSIVEly.
*
* Notes:
*
* ■ If a filter is set in the current work area, the insert
* will still be performed properly and the inserted record
* will be the current record after the insert. Whatever
* actions you take subsequently (assigning values to fields
* and moving the record pointer) may bring the record out
* of the scope of the filter.
*
* ■ If any indexes are active in the current work area, they
* will be updated, but the record will be inserted
* according to the current record's PHYSICAL location.
* Presumably, you have a need to maintain the file in
* physical order and it wouldn't HAVE any active
* indexes...but who knows what goes on in your strange
* little mind? ;-)
*
* ■ This function will work with any size DBF, but it's
* intended use is with relatively small ones.
* $EXAMPLES$
* ft_dbins() // inserts blank record AFTER current one
* ft_dbins( .f. ) // inserts blank record AFTER current one
* ft_dbins( .t. ) // inserts blank record BEFORE current one
*
* // or, if UDC's are your thing...
*
* #command INSERT [<b4: BEFORE>] => ft_dbins( <.b4.> )
*
* INSERT // inserts blank record AFTER current one
* INSERT BEFORE // inserts blank record BEFORE current one
* $SEEALSO$
*
* $INCLUDE$
*
* $END$
*/
#ifdef FT_TEST
//--------------------------------------------------------------------------//
FUNCTION TestDriver
//--------------------------------------------------------------------------//
#command LIST => ;
set filter to ;;
dbgotop() ;;
dbeval( { || qqout( ltrim( str( recno() ) ), FAM->cName, FAM->dBirth, ;
FAM->nDaysOld, FAM->lIsGirl, FAM->mNotes ), qout() } ) ;;
set filter to FAM->lIsGirl
#command PAUSE <c> => ;
qout( 'Press (almost) any key to insert ' + <c> + '...' ) ;;
inkey( 0 ) ;;
qout() ;;
qout()
dbcreate( 'FT_DBINS', { ;
{ 'cName', 'C', 7, 0 }, ;
{ 'dBirth', 'D', 8, 0 }, ;
{ 'nDaysOld', 'N', 5, 0 }, ;
{ 'lIsGirl', 'L', 1, 0 }, ;
{ 'mNotes', 'M', 10, 0 } } )
use FT_DBINS alias FAM exclusive
set filter to FAM->lIsGirl
append blank
FAM->cName := 'Ryan'
FAM->dBirth := ctod( '6/6/85' )
FAM->nDaysOld := date() - FAM->dBirth
FAM->lIsGirl := .f.
FAM->mNotes := 'Likes to play Word Rescue.'
append blank
FAM->cName := 'Amanda'
FAM->dBirth := ctod( '10/2/90' )
FAM->nDaysOld := date() - FAM->dBirth
FAM->lIsGirl := .t.
FAM->mNotes := 'Likes Minnie Mouse.'
cls
list
pause 'Susan before Ryan'
goto 1
ft_dbins( .t. )
FAM->cName := 'Susan'
FAM->dBirth := ctod( '12/21/61' )
FAM->nDaysOld := date() - FAM->dBirth
FAM->lIsGirl := .t.
FAM->mNotes := "Likes Todd (except when he's on the PC ;-)."
list
pause 'Zachary after Ryan'
goto 2
ft_dbins()
FAM->cName := 'Zachary'
FAM->dBirth := ctod( '2/27/88' )
FAM->nDaysOld := date() - FAM->dBirth
FAM->lIsGirl := .f.
FAM->mNotes := 'Likes Barney.'
list
pause 'Emily after Amanda'
goto 4
ft_dbins( .f. )
FAM->cName := 'Emily'
FAM->dBirth := ctod( '2/20/92' )
FAM->nDaysOld := date() - FAM->dBirth
FAM->lIsGirl := .t.
FAM->mNotes := "Likes to eat and sleep (just like dad ;-)."
list
close database
erase FT_DBINS.dbf
erase FT_DBINS.dbt
RETURN nil
//--------------------------------------------------------------------------//
#endif
//--------------------------------------------------------------------------//
FUNCTION ft_dbins( lBefore )
//--------------------------------------------------------------------------//
/*
Modus Operandi:
1) Append a blank record at the end of the file.
2) Back up through the file, "moving" each record down one position
(preserving it's deleted() status) until the current record plus 1 is
reached (or current record if inserting BEFORE).
3) Blank out the "inserted" record and recall() it if it's deleted().
Please note that "goto recno() + 1" is used in place of dbskip() and "goto
recno() - 1" is used in place of dbskip ( -1 ). This effectively defeats
any filter and eliminates the need to save and restore the filter condition
via the macro operator.
*/
#define DBS_NAME 1
#define FLD_BLK 1
#define FLD_VAL 2
LOCAL nRec := recno() + 1
LOCAL lSavDel := set( _SET_DELETED, .f. )
LOCAL nSavOrd := indexord()
LOCAL aFields := {}
LOCAL lDeleted := .f.
IF lBefore = nil; lBefore := .f.; ENDIF
IF lBefore
// stop moving records when the current record is reached
--nRec
ENDIF
// build the array of field get/set blocks with cargo space for field values
aeval( dbstruct(), { | a | ;
aadd( aFields, { fieldblock( a[ DBS_NAME ] ), nil } ) } )
// process in physical order
dbsetorder( 0 )
// add a new record at eof
dbappend()
// back up through the file moving records down as we go
WHILE recno() > nRec
// store all values from previous record in the appropriate cargo space
goto recno() - 1
aeval( aFields, { | a | a[ FLD_VAL ] := eval( a[ FLD_BLK ] ) } )
// save deleted status
lDeleted := deleted()
// replace all values in next record with stored cargo values
goto recno() + 1
aeval( aFields, { | a | eval( a[ FLD_BLK ], a[ FLD_VAL ] ) } )
// set deleted status
iif( lDeleted, dbdelete(), dbrecall() )
// go to previous record
goto recno() - 1
END
// blank out the "inserted" record
aeval( aFields, { | a, cType | ;
cType := valtype( eval( a[ FLD_BLK ] ) ), ;
eval( a[ FLD_BLK ], ;
iif( cType $ 'CM', '', ;
iif( cType = 'N', 0, ;
iif( cType = 'D', ctod( ' / / ' ), ;
iif( cType = 'L', .f., nil ) ) ) ) ) } )
// make sure it's not deleted
dbrecall()
// leave things the way we found them
dbsetorder( nSavOrd )
set( _SET_DELETED, lSavDel )
RETURN nil
//--------------------------------------------------------------------------//