next
previous
top
last
contents
aiuto
indice analitico
tome
part
TXT
HTML
PDF
pdf
gdoc
P4
Clean the Clipper 5.2
A different way to program using Clipper 5.2 without commands, that is, without the file STD.CH
.(1)
Clipper 5.2,(2) as the xBase tradition imposes, is not an ordered, clear, simple programming language. The question is: which is the right way to write a Clipper program? If the intention is not to make a xBase program, but a Clipper program, maybe it can be decided that it is better to use Clipper without commands.
Step 1: try to compile with the /P parameter
Supposing to compile the file TEST.PRG
this way:
C:\>
CLIPPER TEST.PRG /P
[Enter]
It generates a preprocessed output file (test.PPO
), that is a source file without comments, where commands are translated into real Clipper instructions. That is, all the #COMMAND substitution are executed and the translation is sent to the .PPO
file. It may be difficult to read this file the first time.
Step 2: understand well the use of code blocks
The code block is a small piece of executable program code that can be stored inside a variable, or can be used as a literal constant. The good of it, is that pieces of code may be sent to functions.
A code block is something like a little user defined function where only a sequence of expressions (functions and/or assignments) may appear: no loops, no conditional structures.
A code block may receive arguments and return a value after execution, just like a function. The syntax is the following, where curly brackets are part of the code block:
{ | [argument_list] | exp_list }
|
That is: the argument_list is optional; the exp_list may contain one or more expressions separated with a comma.
For example, calling the following code block will give the string ``hello world'' as result.
The following code block requires a numeric argument and returns the number passed as argument incremented:
The following code block requires two numeric arguments and returns the sum of the two square radix:
{ | nFirst, nSecond | SQRT(nFirst) + SQRT(nSecond) }
|
|
But code blocks may contain more expressions and the result of the execution of the code block is the result of the last expression. The following code block executes in sequence some functions and gives ``hello world'' as a result.
{ | a, b | functionOne(a), functionTwo(b), "hello world" }
|
|
To start the execution of a code block a function is used: EVAL(). For example, a code block is assigned to a variable and then executed.
B := { || "hello world" }
EVAL( B ) == "hello world"
|
|
Another example with one parameter.
B := { | n | n+1 }
EVAL( B, 1 ) == 2
|
|
Another example with two parameters.
B := { | nFirst, nSecond | SQRT(nFirst) + SQRT(nSecond) }
EVAL( B, 2, 4 ) == 20
|
|
And so on.
Step 3: understand the object programming
Clipper 5.2 do not permit to create objects, but it gives some good objects to use: GET and TBROWSE. Before starting to clean programming from commands, it is necessary to understand how to use well the Clipper objects.
Classes and methods
A class defines the structure of a ``black box'', that is a data container; a method is an action to make on a piece of data contained inside the black box. There is no way to reach the data contained inside the black box without a method.
The black box can be called object.
The methods may be seen as they where special functions which interact with a specific piece of data contained inside the object.
Class definition
Supposing that Clipper permits to define classes (unluckily only predefined classes can be used), the hypothetical syntax could be:
CLASS ClassName [FROM ParentClass]
VAR Var1 [,Var2[,...VarN]]
METHOD {method_definition_1} [, ...{method_definition_n} ]
ENDCLASS
|
This way, the class defines a group of variables and a group of method to use with these variables.
Object creation
The presence of classes permits to create objects: the black boxes.
Variable_name := ClassName
|
This way, a variable contains (is) an object. Please note that inside Clipper, an object may be generated also from a function, that is, a function can return an object. This way the example can be:
Variable_name := classfunction( ... )
|
The next problem is to handle this object.
Instantiating an object
As already stated before, methods are used to handle data contained inside an object. This is said to be instantiating an object. Clipper permits also to handle directly (apparently without methods) some variables contained inside objects. These are called ``Exported Instance Variables''. So, an object can be instantiated this way:
object:exported_instance_variable := new_value
|
An exported instance variable may be read and/or modified depending on the allowed access to it; a method, inside Clipper, is something like a function with or without parameters (if parameters are present, these are usually used to modify data inside the object), that normally returns a value.
The ``send'' symbol
To instantiate an object or simply to access an exported instance variable, the ``send'' symbol (colon) is used.
More about objects
If this is not enough to understand objects inside Clipper, the following document should be read:
Peter M. Freese, o:Clip - An Object Oriented Extension to Clipper 5.01 1991, CyberSoft
ftp://ftp.simtel.net/pub/simtelnet/msdos/clipper/oclip.zip
Step 4: understand the get object
What happens with a command like the following:
A get object is created containing all the necessary information for editing the variable Var at the screen position nTop, nLeft. After that, this get object is added to a get objects array (usually called GetList). The get objects array will contain all the get objects used during a READ.
So, what happens when a READ command is encountered. The get objects array (GetList) is read and the editing of all get objects is executed. After that, the get objects array is cleared.
This method hides what Clipper really makes. The suggestion here is to create a GET() function that will substitute the @...GET command and to use the READMODAL() function to read the get objects array. Here is an example of it:
function GET( aoGet, nRow, nCol, bVar, cGetPicture,
cColorString, bPreValid, bPostValid )
// declare a local get object
local oGet
// create the get object using the function GETENV()
oGet := GETENV( nRow, nCol, bVar, NIL, cGetPicture, cGetColor )
// send to the get object the pre-validation condition code block (WHEN)
oGet:preBlock := bPreValid
// send to the get object the post-validation condition code block (VALID)
oGet:postBlock := bPostValid
// display the get on the screen using the display() method
oGet:display()
// add the get object to the get objects array
AADD( aoGet, oGet )
return NIL
|
|
-
aoGet is the get objects array (so here is explicitly passed). This get objects array is modified (grown) and there is no need to return it as inside Clipper, arrays are always passed by reference to functions.
-
nRow and nCol are the screen coordinates where the get field should appear at, as it works with the @...GET command.
-
bVar is a special code block that permits the editing of a variable. If the variable Var is to be edited, the code block is:
{ |x| iif( pcount() > 0, Var := x, Var }
|
|
-
cGetPicture is the picture to use: same as the @...GET command.
-
cColorString is the color string to use: same as the @...GET command.
-
bPreValid is a code block containing the condition that must be valid before the cursor can reach this get field. It is equivalent to the WHEN condition used with the @...GET command, but it must be converted into a code block. For example, if the condition is A > B, the code block is {|| A > B}
-
bPostValid is a code block containing the condition that must be valid before the cursor can leave this get field. It is equivalent to the VALID condition used with the @...GET command, but it must be converted into a code block. For example, if the condition is A > B, the code block is {|| A > B}
If there is a get function like the above one, screen I/O may be performed like the following example:
function do_some_editing()
// define a variable to use as a get objects array
// and initialise it to the empty array
local aoGet := {}
...
...
// add a new get object to the get objects array
get(;
aoGet,;
10, 10,;
{ |x| iif( pcount() > 0, myVariable := x, myVariable },;
"@s30@",;
"gb+/b, n/w, n, n, w/n",;
{ || .T. },;
{ || .T. };
)
...
// read the get objects array
readmodal( aoGet )
// clear the get objects array
aoGet := {}
...
return ...
|
|
If the function GET() is not liked, the above I/O may be done as it follows:
function do_some_editing()
// define a variable to use as a get object
local aoGet
// define a variable to use as a get objects array
// and initialise it to the empty array
local aoGet := {}
...
...
// add a new get object to the get objects array
oGet :=;
GETENV(;
10, 10,;
{ |x| iif( pcount() > 0, myVariable := x, myVariable },;
NIL,;
"@s30@",;
"gb+/b, n/w, n, n, w/n",;
)
AADD( aoGet, oGet )
...
// read the get objects array
readmodal( aoGet )
// clear the get objects array
aoGet := {}
...
return ...
|
|
Step 5: trying to stop using commands
To stop using commands, it is important to understand how commands are or may be translated into functions. Sometimes Clipper uses some undocumented functions: these are functions that start with a underline.
?/??
@...BOX
@ nTop, nLeft, nBottom, nRight BOX cnBoxString [COLOR cColorString]
|
dispbox(nTop, nLeft, nBottom, nRight, [cnBoxString], [cColorString])
|
@...GET
@ nTop, nLeft GET Var [PICTURE cGetPicture] [COLOR cColorString] \ \[WHEN lPreExpression] [VALID lPostExpression]
|
aadd( GetList, _GET_( Var, "Var", cGetPicture, [{|| lPostExpression}],\ \[{|| lPreExpression}] ):display() ) atail(GetList):colorDisp(cColorString)
|
This is the command substitution made automatically, but it shouldn't be used to make clean programs. The step 4 (u0.1) suggests to create a get function.
@...SAY
@ nTop, nLeft SAY exp [COLOR cColorString]
|
devout(exp [, cColorString])
|
@ nTop, nLeft SAY exp PICTURE cSayPicture [COLOR cColorString]
|
devoutpic(exp, cSayPicture, [cColorString])
|
@...TO
@ nTop, nLeft TO nBottom, nRight DOUBLE [COLOR cColorString]
|
dispbox(nTop, nLeft, nBottom, nRight, 2 [,cColorString])
|
@ nTop, nLeft TO nBottom, nRight [COLOR cColorString]
|
dispbox(nTop, nLeft, nBottom, nRight, 1 [,cColorString])
|
@ nTop, nLeft CLEAR [TO nBottom, nRight]
|
scroll([nTop], [nLeft], [nBottom, nRight])
|
APPEND
APPEND FROM
APPEND FROM xcFile [FIELDS idField_list] [scope] [WHILE lCondition]\ \[FOR lCondition] [VIA xcDriver]
|
__dbApp( cFileName, [acFields], [bForCondition], [bWhileCondition], [nNextRecords],\ \[nRecord], [lRest], [cDriver] )
|
APPEND FROM xcFile [FIELDS idField_list] [scope] [WHILE lCondition] [FOR lCondition]\ \DELIMITED xcDelimiter
|
__dbDelim( .f., cFileName, [cDelimiter], [acFields], [bForCondition], \ \[bWhileCondition], [nNextRecords], [nRecord], [lRest] )
|
APPEND FROM xcFile [FIELDS idField_list] [scope] [WHILE lCondition]\ \[FOR lCondition] SDF
|
__dbSDF( .f., cFileName, [acFields], [bForCondition], [bWhileCondition], \ \[nNextRecords], [nRecord], [lRest] )
|
CLEAR
CLOSE
idAlias->( dbCloseArea() )
|
COMMIT
CONTINUE
COPY
COPY FILE xcSourceFile TO xcTargetFile|xcDevice
|
__CopyFile( cSourceFile, cTargetFile|cDevice )
|
COPY STRUCTURE [FIELDS idField_list] TO xcDatabase
|
__dbCopyStruct( cDatabase, [acFields] )
|
COPY STRUCTURE EXTENDED TO xcExtendedDatabase
|
__dbCopyXStruct( cExtendedDatabase )
|
COPY TO xcFile [FIELDS idField_list] [scope] [WHILE lCondition]\ \[FOR lCondition] [VIA xcDriver]
|
__dbCopy( cFileName, [acFields], [bForCondition], [bWhileCondition], [nNextRecords],\ \[nRecord], [lRest], [cDriver] )
|
COPY TO xcFile [FIELDS idField_list] [scope] [WHILE lCondition] [FOR lCondition]\ \DELIMITED xcDelimiter
|
__dbDelim( .t., cFileName, [cDelimiter], [acFields], [bForCondition], \ \[bWhileCondition], [nNextRecords], [nRecord], [lRest] )
|
COPY TO xcFile [FIELDS idField_list] [scope] [WHILE lCondition]\ \[FOR lCondition] SDF
|
__dbSDF( .t., cFileName, [acFields], [bForCondition], [bWhileCondition], \ \[nNextRecords], [nRecord], [lRest] )
|
COUNT
COUNT TO idVar [FOR lForCondition] [WHILE lWhileCondition] [NEXT nNextRecords]\ \[RECORD nRecord] [REST] [ALL]
|
dbeval( {||idVar:=idVar+1}, {||lForCondition}, {||lWhileCondition},\ \nNextRecords, nRecord, lRest )
|
CREATE
CREATE xcDatabase FROM xcExtendedDatabase [NEW] [ALIAS cAlias] [VIA cDriver]
|
__dbCreate( cDatabase, cExtendedDatabase, [cDriver], [lNew], [cAlias] )
|
DEFAULT
DEFAULT xVar TO xDefaultValue
|
if xVar == NIL
xVar := xDefaultValue
end
|
DELETE
DELETE [FOR lForCondition] [WHILE lWhileCondition] [NEXT nNextRecords]\ \[RECORD nRecord] [REST] [ALL]
|
dbeval( {||dbDelete()}, {||lForCondition}, {||lWhileCondition},\ \nNextRecords, nRecord, lRest )
|
EJECT
ERASE
FIND
GO
INDEX ON
INDEX ON expKey TO xcIndexName [UNIQUE] [FOR lForCondition]\ \[WHILE lWhileCondition] [[EVAL lEvalCondition] [EVERY nRecords]] \ \[ASCENDING|DESCENDING]
|
ordCondSet( [cForCondition], [bForCondition], , [bWhileCondition],\ \[bEvalCondition], [nRecords], RECNO(), , , , lDescending )
|
ordCreate( cIndexName, , cExpKey, bExpKey, lUnique )
|
JOIN
JOIN WITH xcAlias TO xcDatabase [FOR lCondition] [FIELDS idField_list]
|
__dbJoin( cAlias, cDatabase, [acFields], [bForCondition] )
|
KEYBOARD
__Keyboard( [cString] ) --> NIL
|
LABEL FORM
LABEL FORM xcLabel [TO PRINTER] [TO FILE xcFile] [NOCONSOLE] [scope]\ \[WHILE lCondition] [FOR lCondition] [SAMPLE]
|
__LabelForm( cLabel, [lToPrinter], [cFile], [lNoConsole],\ \[bForCondition], [bWhileCondition], [nNextRecords], [nRecord], \ \[lRest], [lSample] )
|
LIST
LIST exp_list [TO PRINTER] [TO FILE xcFile] [scope]\ \[WHILE lCondition] [FOR lCondition] [OFF]
|
__dbList( [lToDisplay], abListColumns, [lAll], [bForCondition], [bWhileCondition],\ \[nNextRecords], [nRecord], [lRest], [lToPrinter], [cFileName] )
|
LOCATE
LOCATE [scope] FOR lCondition [WHILE lCondition]
|
__dbLocate( [bForCondition], [bWhileCondition], [nNextRecords], [nRecord], [lRest] )
|
PACK
QUIT
READ
RECALL
RECALL [FOR lForCondition] [WHILE lWhileCondition] [NEXT nNextRecords]\ \[RECORD nRecord] [REST] [ALL]
|
dbeval( {||dbRecall()}, {||lForCondition}, {||lWhileCondition},\ \nNextRecords, nRecord, lRest )
|
REINDEX
REINDEX [EVAL lEvalCondition] [EVERY nRecords]
|
ordCondSet(, , , , [bEvalCondition], [nRecords], , , , , , , )
|
RELEASE
__MXRelease( "idMemvar" )
|
RELEASE ALL LIKE skeleton
|
__MRelease( "skeleton", .t. )
|
RELEASE ALL EXCEPT skeleton
|
__MRelease( "skeleton", .F. )
|
RENAME
RENAME xcOldFile TO xcNewFile
|
frename( cOldFile, cNewFile )
|
REPLACE
REPLACE idField1 WITH exp1 [, idField2 WITH exp2...]\ \[FOR lForCondition] [WHILE lWhileCondition] [NEXT nNextRecords] \ \[RECORD nRecord] [REST] [ALL]
|
dbeval( {|| idField1 := exp1 [, idField2 := exp2...]},\ \{||lForCondition}, {||lWhileCondition}, nNextRecords, \ \nRecord, lRest )
|
REPLACE idField1 WITH exp1
|
REPORT FORM
REPORT FORM xcReport [TO PRINTER] [TO FILE xcFile] [NOCONSOLE] [scope]\ \[WHILE lCondition] [FOR lCondition] [PLAIN | HEADING cHeading] [NOEJECT] \ \[SUMMARY]
|
__ReportForm( cForm, [lToPrinter], [cToFile], [lNoConsole], [bForCondition], \ \[bWhileCondition], [nNext], [nRecord], [lRest], [lPlain], [cbHeading], \ \[lBeforeEject], [lSummary] )
|
RESTORE
RESTORE SCREEN FROM cScreen
|
restscreen( 0, 0, Maxrow(), Maxcol(), cScreen )
|
RESTORE FROM
RESTORE FROM xcMemFile [ADDITIVE]
|
__MRestore( cMemFileName, [lAdditive] )
|
RUN
SAVE SCREEN TO
cScreen := savescreen( 0, 0, maxrow(), maxcol() )
|
SAVE TO
SAVE TO xcMemFile [ALL [LIKE|EXCEPT skeleton]]
|
_MSave( cMemFileName, [cSkeleton], [lLike] )
|
SEEK
SEEK expSearch [SOFTSEEK]
|
dbSeek( expSearch [, lSoftSeek] )
|
SELECT
SELECT xnWorkArea | idAlias
|
dbSelectArea( nWorkArea | cIdAlias )
|
SET
Most of the SET... commands are translated into the SET() function that distinguishes different modes depending on a number. As this number is difficult to handle during programming (essentially because it is difficult to remember the meaning of it), Clipper offers the SET.CH include file that helps with manifest constants.
#define _SET_EXACT 1
#define _SET_FIXED 2
#define _SET_DECIMALS 3
#define _SET_DATEFORMAT 4
#define _SET_EPOCH 5
#define _SET_PATH 6
#define _SET_DEFAULT 7
#define _SET_EXCLUSIVE 8
#define _SET_SOFTSEEK 9
#define _SET_UNIQUE 10
#define _SET_DELETED 11
#define _SET_CANCEL 12
#define _SET_DEBUG 13
#define _SET_TYPEAHEAD 14
#define _SET_COLOR 15
#define _SET_CURSOR 16
#define _SET_CONSOLE 17
#define _SET_ALTERNATE 18
#define _SET_ALTFILE 19
#define _SET_DEVICE 20
#define _SET_EXTRA 21
#define _SET_EXTRAFILE 22
#define _SET_PRINTER 23
#define _SET_PRINTFILE 24
#define _SET_MARGIN 25
#define _SET_BELL 26
#define _SET_CONFIRM 27
#define _SET_ESCAPE 28
#define _SET_INSERT 29
#define _SET_EXIT 30
#define _SET_INTENSITY 31
#define _SET_SCOREBOARD 32
#define _SET_DELIMITERS 33
#define _SET_DELIMCHARS 34
#define _SET_WRAP 35
#define _SET_MESSAGE 36
#define _SET_MCENTER 37
#define _SET_SCROLLBREAK 38
|
|
SET ALTERNATE TO xcFile [ADDITIVE]
|
Set( _SET_ALTFILE, cFile, lAdditive )
|
SET ALTERNATE ON | OFF | xlToggle
|
Set( _SET_ALTERNATE, "ON" | "OFF" | lToggle )
|
SET BELL ON | OFF | xlToggle
|
Set( _SET_BELL, "ON" | "OFF" | lToggle )
|
SET COLOR | COLOUR TO (cColorString)
|
SET CONFIRM ON | OFF | xlToggle
|
Set( _SET_CONFIRM, "ON" | "OFF" | lToggle )
|
SET CONSOLE ON | OFF | xlToggle
|
Set( _SET_CONSOLE, "ON" | "OFF" | lToggle )
|
SET CURSOR ON | OFF | xlToggle
|
SetCursor( 1 | 0 | iif( lToggle, 1, 0 ) )
|
SET DATE FORMAT [TO] cDateFormat
|
Set( _SET_DATEFORMAT, cDateFormat )
|
SET DECIMALS TO nDecimals
|
Set( _SET_DECIMALS, nDecimals )
|
SET DEFAULT TO xcPathspec
|
Set( _SET_DEFAULT, cPathspec )
|
SET DELETED ON | OFF | xlToggle
|
Set( _SET_DELETED, "ON" | "OFF" | lToggle )
|
SET DELIMITERS ON | OFF | xlToggle
|
Set( _SET_DELIMITERS, "ON" | "OFF" | lToggle )
|
SET DELIMITERS TO [DEFAULT]
|
Set( _SET_DELIMCHARS, "::" )
|
SET DELIMITERS TO cDelimiters
|
Set( _SET_DELIMCHARS, cDelimiters )
|
SET DEVICE TO SCREEN | PRINTER
|
Set( _SET_DEVICE, "SCREEN" | "PRINTER" )
|
SET ESCAPE ON | OFF | xlToggle
|
Set( _SET_ESCAPE, "ON" | "OFF" | lToggle )
|
SET EXACT ON | OFF | xlToggle
|
Set( _SET_EXACT, "ON" | "OFF" | lToggle )
|
SET EXCLUSIVE ON | OFF | xlToggle
|
Set( _SET_EXCLUSIVE, "ON" | "OFF" | lToggle )
|
dbsetfilter( bCondition, cCondition )
|
SET FIXED ON | OFF | xlToggle
|
Set( _SET_FIXED, "ON" | "OFF" | lToggle )
|
SET FUNCTION nFunctionKey TO cString
|
__SetFunction( nFunctionKey, cString )
|
SET INDEX TO [xcIndex [, xcIndex1... ] ]
|
ordListAdd( cIndex )
ordListAdd( cIndex1 )
...
|
SET INTENSITY ON | OFF | xlToggle
|
Set( _SET_INTENSITY, "ON" | "OFF" | lToggle )
|
SetKey( nInkeyCode, NIL )
|
SET KEY nInkeyCode TO [idProcedure]
|
SetKey( nInkeyCode, { |p, l, v| idProcedure(p, l, v)} )
|
SET MARGIN TO [nPageOffset]
|
Set( _SET_MARGIN, nPageOffset )
|
SET MESSAGE TO [nRow [CENTER | CENTRE]]
|
Set( _SET_MESSAGE, nRow )
|
Set( _SET_MCENTER, lCenter )
|
SET PATH TO [xcPathspec [, cPathspec1... ] ]
|
Set( _SET_PATH, cPathspec [, cPathspec1... ] )
|
SET PRINTER ON | OFF | xlToggle
|
Set( _SET_PRINTER, "ON" | "OFF" | lToggle )
|
Set( _SET_PRINTFILE, "" )
|
SET PRINTER TO [xcDevice|xcFile [ADDITIVE]]
|
Set( _SET_PRINTFILE, cDevice|cFile, lAdditive )
|
SET RELATION TO [expKey1 INTO xcAlias1] [, [TO] expKey2 INTO xcAlias2...]
|
dbSetRelation( cAlias1, {||expKey1}, ["expKey1"] )
|
dbSetRelation( cAlias2, {||expKey2}, ["expKey1"] )
|
SET RELATION TO [expKey1 INTO xcAlias1]\ \[, [TO] expKey2 INTO xcAlias2...] ADDITIVE
|
dbSetRelation( cAlias1, {||expKey1}, ["expKey1"] )
|
dbSetRelation( cAlias2, {||expKey2}, ["expKey1"] )
|
SET SCOREBOARD ON | OFF | xlToggle
|
Set( _SET_SCOREBOARD, "ON" | "OFF" | lToggle )
|
SET SOFTSEEK ON | OFF | xlToggle
|
Set( _SET_SOFTSEEK, "ON" | "OFF" | lToggle )
|
SET TYPEAHEAD TO nKeyboardSise
|
Set( _SET_TYPEAHEAD, nKeyboardSise )
|
SET UNIQUE ON | OFF | xlToggle
|
Set( _SET_UNIQUE, "ON" | "OFF" | lToggle )
|
SET WRAP ON | OFF | xlToggle
|
Set( _SET_WRAP, "ON" | "OFF" | lToggle )
|
SKIP
SKIP [nRecords] [ALIAS idAlias|nWorkArea]
|
[idAlias|nWorkArea -> ]( dbSkip([nRecords]) )
|
SORT
SORT TO xcDatabase ON idField1 [/[A|D][C]] [, idField2 [/[A|D][C]] ...]\ \[scope] [WHILE lCondition] [FOR lCondition]
|
__dbSort( cDatabase, [acFields], [bForCondition], [bWhileCondition],\ \[nNextRecords], [nRecord], [lRest] )
|
STORE
SUM
SUM nExp1 [, nExp2...] TO idVar1 [, idVar2...] [FOR lForCondition]\ \[WHILE lWhileCondition] [NEXT nNextRecords] [RECORD nRecord] [REST] [ALL]
|
dbeval( {||idVar1:=idVar1+nExp1 [, idVar2:=idVar2+nExp2...] },\ \{||lForCondition}, {||lWhileCondition}, nNextRecords, nRecord, lRest )
|
TOTAL ON
TOTAL ON expKey [FIELDS idField_list] TO xcDatabase [scope]\ \[WHILE lCondition] [FOR lCondition]
|
__dbTotal( cDatabase, bKey, [acFields], [bForCondition], [bWhileCondition],\ \[nNextRecords], [nRecord], [lRest] )
|
UNLOCK
UPDATE FROM
UPDATE FROM xcAlias ON expKey [RANDOM] REPLACE idField1\ \WITH exp [, idField2 WITH exp ...]
|
__dbUpdate( cAlias, bKey, [lRandom], [bReplacement] )
|
Example:
__dbUpdate( "INVOICE", {|| LAST}, .T.,; {|| FIELD->TOTAL1 := \ \INVOICE->SUM1,; FIELD->TOTAL2 := INVOICE->SUM2 } )
|
|
USE
USE [xcDatabase]\ \[INDEX xcIndex1 [, xcIndex2...] [ALIAS xcAlias] [EXCLUSIVE|SHARED] [NEW] \ \[READONLY] [VIA cDriver]]
|
dbUseArea( [lNewArea], [cDriver], cDatabase, [cAlias], [lShared], [lReadOnly] )
|
ZAP
Step 6: free yourself from STD.CH - /U
Now that no command is used, the standard include file STD.CH
is no more necessary. Clipper uses STD.CH
automatically, unless specified differently. Just compile this way:
C:>
CLIPPER TEST.PRG /U
[Enter]
Step 7: take control over all include files
Clipper comes with so many include files (*.CH
). To avoid confusion, a single STANDARD.CH
file containing all what is needed for the application may be prepared. At least, it is necessary the following.
*=================================================================
* DISPBOX()
*=================================================================
* Single-line box
#define BOX_SINGLE;
(;
CHR(218) +;
CHR(196) +;
CHR(191) +;
CHR(179) +;
CHR(217) +;
CHR(196) +;
CHR(192) +;
CHR(179);
)
* Double-line box
#define BOX_DOUBLE;
(;
CHR(201) +;
CHR(205) +;
CHR(187) +;
CHR(186) +;
CHR(188) +;
CHR(205) +;
CHR(200) +;
CHR(186);
)
* Single-line top, double-line sides
#define BOX_SINGLE_DOUBLE;
(;
CHR(214) +;
CHR(196) +;
CHR(183) +;
CHR(186) +;
CHR(189) +;
CHR(196) +;
CHR(211) +;
CHR(186);
)
* Double-line top, single-line sides
#define BOX_DOUBLE_SINGLE;
(;
CHR(213) +;
CHR(205) +;
CHR(184) +;
CHR(179) +;
CHR(190) +;
CHR(205) +;
CHR(212) +;
CHR(179);
)
*=================================================================
* ERRORS
*=================================================================
* Severity levels (e:severity)
#define ERROR_SEVERITY_WHOCARES 0
#define ERROR_SEVERITY_WARNING 1
#define ERROR_SEVERITY_ERROR 2
#define ERROR_SEVERITY_CATASTROPHIC 3
* Generic error codes (e:genCode)
#define ERROR_GENERIC_ARG 1
#define ERROR_GENERIC_BOUND 2
#define ERROR_GENERIC_STROVERFLOW 3
#define ERROR_GENERIC_NUMOVERFLOW 4
#define ERROR_GENERIC_ZERODIV 5
#define ERROR_GENERIC_NUMERR 6
#define ERROR_GENERIC_SYNTAX 7
#define ERROR_GENERIC_COMPLEXITY 8
#define ERROR_GENERIC_MEM 11
#define ERROR_GENERIC_NOFUNC 12
#define ERROR_GENERIC_NOMETHOD 13
#define ERROR_GENERIC_NOVAR 14
#define ERROR_GENERIC_NOALIAS 15
#define ERROR_GENERIC_NOVARMETHOD 16
#define ERROR_GENERIC_BADALIAS 17
#define ERROR_GENERIC_DUPALIAS 18
#define ERROR_GENERIC_CREATE 20
#define ERROR_GENERIC_OPEN 21
#define ERROR_GENERIC_CLOSE 22
#define ERROR_GENERIC_READ 23
#define ERROR_GENERIC_WRITE 24
#define ERROR_GENERIC_PRINT 25
#define ERROR_GENERIC_UNSUPPORTED 30
#define ERROR_GENERIC_LIMIT 31
#define ERROR_GENERIC_CORRUPTION 32
#define ERROR_GENERIC_DATATYPE 33
#define ERROR_GENERIC_DATAWIDTH 34
#define ERROR_GENERIC_NOTABLE 35
#define ERROR_GENERIC_NOORDER 36
#define ERROR_GENERIC_SHARED 37
#define ERROR_GENERIC_UNLOCKED 38
#define ERROR_GENERIC_READONLY 39
#define ERROR_GENERIC_APPENDLOCK 40
#define ERROR_GENERIC_LOCK 41
*=================================================================
* INKEY()
*=================================================================
#define K_UP 5 // Up arrow, Ctrl-E
#define K_DOWN 24 // Down arrow, Ctrl-X
#define K_LEFT 19 // Left arrow, Ctrl-S
#define K_RIGHT 4 // Right arrow, Ctrl-D
#define K_HOME 1 // Home, Ctrl-A
#define K_END 6 // End, Ctrl-F
#define K_PGUP 18 // PgUp, Ctrl-R
#define K_PGDN 3 // PgDn, Ctrl-C
#define K_CTRL_UP 397 // * Ctrl-Up arrow
#define K_CTRL_DOWN 401 // * Ctrl-Down arrow
#define K_CTRL_LEFT 26 // Ctrl-Left arrow, Ctrl-Z
#define K_CTRL_RIGHT 2 // Ctrl-Right arrow, Ctrl-B
#define K_CTRL_HOME 29 // Ctrl-Home, Ctrl-</synsqb>
#define K_CTRL_END 23 // Ctrl-End, Ctrl-W
#define K_CTRL_PGUP 31 // Ctrl-PgUp, Ctrl-Hyphen
#define K_CTRL_PGDN 30 // Ctrl-PgDn, Ctrl-^
#define K_ALT_UP 408 // * Alt-Up arrow
#define K_ALT_DOWN 416 // * Alt-Down arrow
#define K_ALT_LEFT 411 // * Alt-Left arrow
#define K_ALT_RIGHT 413 // * Alt-Right arrow
#define K_ALT_HOME 407 // * Alt-Home
#define K_ALT_END 415 // * Alt-End
#define K_ALT_PGUP 409 // * Alt-PgUp
#define K_ALT_PGDN 417 // * Alt-PgDn
#define K_ENTER 13 // Enter, Ctrl-M
#define K_RETURN 13 // Return, Ctrl-M
#define K_SPACE 32 // Space bar
#define K_ESC 27 // Esc, Ctrl-<synsqb>
#define K_CTRL_ENTER 10 // Ctrl-Enter
#define K_CTRL_RETURN 10 // Ctrl-Return
#define K_CTRL_RET 10 // Ctrl-Return (Compat.)
#define K_CTRL_PRTSCR 379 // * Ctrl-Print Screen
#define K_CTRL_QUESTION 309 // Ctrl-?
#define K_ALT_ENTER 284 // * Alt-Enter
#define K_ALT_RETURN 284 // * Alt-Return
#define K_ALT_EQUALS 387 // * Alt-Equals
#define K_ALT_ESC 257 // * Alt-Esc
#define KP_ALT_ENTER 422 // * Keypad Alt-Enter
#define KP_CTRL_5 399 // * Keypad Ctrl-5
#define KP_CTRL_SLASH 405 // * Keypad Ctrl-/
#define KP_CTRL_ASTERISK 406 // * Keypad Ctrl-*
#define KP_CTRL_MINUS 398 // * Keypad Ctrl--
#define KP_CTRL_PLUS 400 // * Keypad Ctrl-+
#define KP_ALT_5 5 // * Keypad Alt-5
#define KP_ALT_SLASH 420 // * Keypad Alt-/
#define KP_ALT_ASTERISK 311 // * Keypad Alt-*
#define KP_ALT_MINUS 330 // * Keypad Alt--
#define KP_ALT_PLUS 334 // * Keypad Alt-+
#define K_INS 22 // Ins, Ctrl-V
#define K_DEL 7 // Del, Ctrl-G
#define K_BS 8 // Backspace, Ctrl-H
#define K_TAB 9 // Tab, Ctrl-I
#define K_SH_TAB 271 // Shift-Tab
#define K_CTRL_INS 402 // * Ctrl-Ins
#define K_CTRL_DEL 403 // * Ctrl-Del
#define K_CTRL_BS 127 // Ctrl-Backspace
#define K_CTRL_TAB 404 // * Ctrl-Tab
#define K_ALT_INS 418 // * Alt-Ins
#define K_ALT_DEL 419 // * Alt-Del
#define K_ALT_BS 270 // * Alt-Backspace
#define K_ALT_TAB 421 // * Alt-Tab
#define K_CTRL_A 1 // Ctrl-A, Home
#define K_CTRL_B 2 // Ctrl-B, Ctrl-Right arrow
#define K_CTRL_C 3 // Ctrl-C, PgDn, Ctrl-ScrollLock
#define K_CTRL_D 4 // Ctrl-D, Right arrow
#define K_CTRL_E 5 // Ctrl-E, Up arrow
#define K_CTRL_F 6 // Ctrl-F, End
#define K_CTRL_G 7 // Ctrl-G, Del
#define K_CTRL_H 8 // Ctrl-H, Backspace
#define K_CTRL_I 9 // Ctrl-I, Tab
#define K_CTRL_J 10 // Ctrl-J
#define K_CTRL_K 11 // Ctrl-K
#define K_CTRL_L 12 // Ctrl-L
#define K_CTRL_M 13 // Ctrl-M, Return
#define K_CTRL_N 14 // Ctrl-N
#define K_CTRL_O 15 // Ctrl-O
#define K_CTRL_P 16 // Ctrl-P
#define K_CTRL_Q 17 // Ctrl-Q
#define K_CTRL_R 18 // Ctrl-R, PgUp
#define K_CTRL_S 19 // Ctrl-S, Left arrow
#define K_CTRL_T 20 // Ctrl-T
#define K_CTRL_U 21 // Ctrl-U
#define K_CTRL_V 22 // Ctrl-V, Ins
#define K_CTRL_W 23 // Ctrl-W, Ctrl-End
#define K_CTRL_X 24 // Ctrl-X, Down arrow
#define K_CTRL_Y 25 // Ctrl-Y
#define K_CTRL_Z 26 // Ctrl-Z, Ctrl-Left arrow
#define K_ALT_A 286 // Alt-A
#define K_ALT_B 304 // Alt-B
#define K_ALT_C 302 // Alt-C
#define K_ALT_D 288 // Alt-D
#define K_ALT_E 274 // Alt-E
#define K_ALT_F 289 // Alt-F
#define K_ALT_G 290 // Alt-G
#define K_ALT_H 291 // Alt-H
#define K_ALT_I 279 // Alt-I
#define K_ALT_J 292 // Alt-J
#define K_ALT_K 293 // Alt-K
#define K_ALT_L 294 // Alt-L
#define K_ALT_M 306 // Alt-M
#define K_ALT_N 305 // Alt-N
#define K_ALT_O 280 // Alt-O
#define K_ALT_P 281 // Alt-P
#define K_ALT_Q 272 // Alt-Q
#define K_ALT_R 275 // Alt-R
#define K_ALT_S 287 // Alt-S
#define K_ALT_T 276 // Alt-T
#define K_ALT_U 278 // Alt-U
#define K_ALT_V 303 // Alt-V
#define K_ALT_W 273 // Alt-W
#define K_ALT_X 301 // Alt-X
#define K_ALT_Y 277 // Alt-Y
#define K_ALT_Z 300 // Alt-Z
#define K_ALT_1 376 // Alt-1
#define K_ALT_2 377 // Alt-2
#define K_ALT_3 378 // Alt-3
#define K_ALT_4 379 // Alt-4
#define K_ALT_5 380 // Alt-5
#define K_ALT_6 381 // Alt-6
#define K_ALT_7 382 // Alt-7
#define K_ALT_8 383 // Alt-8
#define K_ALT_9 384 // Alt-9
#define K_ALT_0 385 // Alt-0
#define K_F1 28 // F1, Ctrl-Backslash
#define K_F2 -1 // F2
#define K_F3 -2 // F3
#define K_F4 -3 // F4
#define K_F5 -4 // F5
#define K_F6 -5 // F6
#define K_F7 -6 // F7
#define K_F8 -7 // F8
#define K_F9 -8 // F9
#define K_F10 -9 // F10
#define K_F11 -40 // * F11
#define K_F12 -41 // * F12
#define K_CTRL_F1 -20 // Ctrl-F1
#define K_CTRL_F2 -21 // Ctrl-F2
#define K_CTRL_F3 -22 // Ctrl-F4
#define K_CTRL_F4 -23 // Ctrl-F3
#define K_CTRL_F5 -24 // Ctrl-F5
#define K_CTRL_F6 -25 // Ctrl-F6
#define K_CTRL_F7 -26 // Ctrl-F7
#define K_CTRL_F8 -27 // Ctrl-F8
#define K_CTRL_F9 -28 // Ctrl-F9
#define K_CTRL_F10 -29 // Ctrl-F10
#define K_CTRL_F11 -44 // * Ctrl-F11
#define K_CTRL_F12 -45 // * Ctrl-F12
#define K_ALT_F1 -30 // Alt-F1
#define K_ALT_F2 -31 // Alt-F2
#define K_ALT_F3 -32 // Alt-F3
#define K_ALT_F4 -33 // Alt-F4
#define K_ALT_F5 -34 // Alt-F5
#define K_ALT_F6 -35 // Alt-F6
#define K_ALT_F7 -36 // Alt-F7
#define K_ALT_F8 -37 // Alt-F8
#define K_ALT_F9 -38 // Alt-F9
#define K_ALT_F10 -39 // Alt-F10
#define K_ALT_F11 -46 // * Alt-F11
#define K_ALT_F12 -47 // * Alt-F12
#define K_SH_F1 -10 // Shift-F1
#define K_SH_F2 -11 // Shift-F2
#define K_SH_F3 -12 // Shift-F3
#define K_SH_F4 -13 // Shift-F4
#define K_SH_F5 -14 // Shift-F5
#define K_SH_F6 -15 // Shift-F6
#define K_SH_F7 -16 // Shift-F7
#define K_SH_F8 -17 // Shift-F8
#define K_SH_F9 -18 // Shift-F9
#define K_SH_F10 -19 // Shift-F10
#define K_SH_F11 -42 // * Shift-F11
#define K_SH_F12 -43 // * Shift-F12
*=================================================================
* MEMOEDIT()
*=================================================================
* User function entry modes
#define MEMOEDIT_IDLE 0 // idle, all keys processed
#define MEMOEDIT_UNKEY 1 // unknown key, memo unaltered
#define MEMOEDIT_UNKEYX 2 // unknown key, memo altered
#define MEMOEDIT_INIT 3 // initialization mode
* User function return codes
#define MEMOEDIT_DEFAULT 0 // perform default action
#define MEMOEDIT_IGNORE 32 // ignore unknown key
#define MEMOEDIT_DATA 33 // treat unknown key as data
#define MEMOEDIT_TOGGLEWRAP 34 // toggle word-wrap mode
#define MEMOEDIT_TOGGLESCROLL 35 // toggle scrolling mode
#define MEMOEDIT_WORDRIGHT 100 // perform word-right operation
#define MEMOEDIT_BOTTOMRIGHT 101 // perform bottom-right operation
*=================================================================
* SET()
*=================================================================
#define _SET_EXACT 1
#define _SET_FIXED 2
#define _SET_DECIMALS 3
#define _SET_DATEFORMAT 4
#define _SET_EPOCH 5
#define _SET_PATH 6
#define _SET_DEFAULT 7
#define _SET_EXCLUSIVE 8
#define _SET_SOFTSEEK 9
#define _SET_UNIQUE 10
#define _SET_DELETED 11
#define _SET_CANCEL 12
#define _SET_DEBUG 13
#define _SET_TYPEAHEAD 14
#define _SET_COLOR 15
#define _SET_CURSOR 16
#define _SET_CONSOLE 17
#define _SET_ALTERNATE 18
#define _SET_ALTFILE 19
#define _SET_DEVICE 20
#define _SET_EXTRA 21
#define _SET_EXTRAFILE 22
#define _SET_PRINTER 23
#define _SET_PRINTFILE 24
#define _SET_MARGIN 25
#define _SET_BELL 26
#define _SET_CONFIRM 27
#define _SET_ESCAPE 28
#define _SET_INSERT 29
#define _SET_EXIT 30
#define _SET_INTENSITY 31
#define _SET_SCOREBOARD 32
#define _SET_DELIMITERS 33
#define _SET_DELIMCHARS 34
#define _SET_WRAP 35
#define _SET_MESSAGE 36
#define _SET_MCENTER 37
#define _SET_SCROLLBREAK 38
*=================================================================
* SETCURSOR()
*=================================================================
#define SETCURSOR_NONE 0 // No cursor
#define SETCURSOR_NORMAL 1 // Normal cursor (underline)
#define SETCURSOR_INSERT 2 // Insert cursor (lower half block)
#define SETCURSOR_SPECIAL1 3 // Special cursor (full block)
#define SETCURSOR_SPECIAL2 4 // Special cursor (upper half block)
*=================================================================
* RDD REQUESTs
*=================================================================
external dbfndx
external dbfntx // default
|
|
1) This material appeared originally at http://www.geocities.com/SiliconValley/7737/clipper52clean.html
, in 1996.
2) Clipper 5.2 Proprietary software
«a2» 2013.11.11 --- Copyright © Daniele Giacomini -- appunti2@gmail.com http://informaticalibera.net