The not equal ( <>) operator compares two values of the same data type and returns true (.T.) if exp1 is not equal to exp2 according to the following rules:
■ Character: The comparison is based on the underlying ASCII
code and is the inverse of the equal operator (=). This means that the comparison is sensitive to the current EXACT SETting. See the examples below.
■ Date: Dates are compared according to the underlying date
value.
■ Logical: False (.F.) is not equal to true (.T.).
■ Memo: Treated the same as character.
■ NIL: All values compared to NIL other than NIL return true
The simple assignment operator (=) assigns a value to a variable. It is identical in operation to the STORE command that initializes a single variable and must be specified as a program statement. The inline assignment operator (:=) is like the = operator except that you can specify it within expressions. If you specify the simple assign operator (=) within an expression, it is interpreted as the equality (=) operator.
Note: You cannot initialize a specific variable using the simple assign operator (=) in a declaration statement. Only the inline assign (:=) operator can be used for this purpose.
If the reference to idVar is ambiguous (i.e., not declared at compile time and not explicitly qualified with an alias), idVar is always assumed to be MEMVAR. At runtime, if no private or public variable exists with the specified name, a private variable is created. To assign a field variable with the = operator, you must declare the field variable name in a FIELD statement or refer to the field name prefaced by the FIELD-> alias or the name of the work area.
Examples
■ These examples are valid simple assignment statements:
nValue = 25
nNewValue = Sqrt(nValue) ** 5
nOldValue = nValue
■ In this example, the two lines are equivalent:
FIELD->CustAge = 20
REPLACE CustAge WITH 20
In addition to the simple and inline assignment operators (= and :=), there are a series of compound assignment operators that perform an operation then assign a value. They have the form:
idVaroperator= exp
Each compound assignment expression is equivalent to the assignment expression:
idVar := ( idVaroperatorexp )
For each data type that supports an operator, the compound assignment operator performs the same operation before performing the assignment operation. The following table details all of the compound operators:
Compound Operators
Operator Defined as Operations
a += b a := (a + b) concatenation, addition
a -= b a := (a - b) concatenation, subtraction
a *= b a := (a * b) multiplication
a /= b a := (a / b) division
a %= b a := (a % b) modulus
a ^= b a := (a ^ b) exponentiation
Note: The exponentiation operator (**) does not have a corresponding compound assignment operator. The exponentiation compound assignment operator is ^=.
Since the compound assignment operators are based on the inline assignment operator (:=), the operation returns the result of its operation as the value of the expression. This means you can use these operators within expressions just like the inline assignment operator (:=).
Examples
■ These examples use the compound addition and concatenation
assignment operator:
// Character (concatenation)
LOCAL cString := "Hello"
? cString += " there" // Result: "Hello there"
// Date (addition)
LOCAL dDate := CToD("12/12/90")
dDate += 12 // Result: 12/24/90
// Numeric (addition)
LOCAL nValue := 10
? Sqrt(nValue += 15) // Result: 5.00
? nValue // Result: 25.00
■ These examples use the compound subtraction and concatenation
assignment operator:
// Character (concatenation)
LOCAL cString := "Hello "
? cString -= "There" // Result: HelloThere
// Date (subtraction)
LOCAL dDate := CToD("12/24/90")
dDate -= 12 // Result: 12/12/90
// Numeric (subtraction)
LOCAL nValue := 10
? newValue := (nValue -= 5) ** 2 // Result: 25
? nValue // Result: 5
■ This example uses the compound multiplication assignment
operator:
LOCAL nValue := 10
? newValue := (nValue *= 5) + 100 // Result: 150
? nValue // Result: 50
■ This example uses the compound division assignment operator:
LOCAL nValue := 10
? newValue := (nValue /= 5) + 100 // Result: 102.00
? nValue // Result: 2.00
■ This example uses the compound modulus assignment operator:
LOCAL nValue := 10
? newValue := (nValue %= 4) * 100 // Result: 200.00
? nValue // Result: 2.00
■ This example uses the compound exponentiation assignment
operator:
LOCAL nValue := 10
? newValue := (nValue ^= 3) + 50 // Result: 1050.00
? nValue // Result: 1000.00
The equal operator (= ) compares two values of the same data type and returns true (.T.) if exp1 is equal to exp2 according to the following rules:
■ Character: The comparison is based on the underlying ASCII
code. ASCII codes for alphabetic characters are ascending (e.g., the code for "A" is 65 and the code for "Z" is 90).
When EXACT is OFF, two character strings are compared according to the following rules. assume two character strings, cLeft and cRight, where the expression to test is (cLeft = cRight):
- If cRight is null, returns true (.T.).
- If Len(cRight) is greater than Len(cLeft), returns false
(.F.).
- Compare all characters in cRight with cLeft. If all
The exactly equal operator (==) is a binary operator that compares two values of the same data type for exact equality depending on the data type. It returns true (.T.) if exp1 is equal to exp2 according to the following rules:
■ Array: Compares for identity. If exp1 and exp2 are
variable references to the same array, returns true (.T.); otherwise, returns false (.F.).
■ Character: Comparison is based on the underlying ASCII code.
ASCII codes for alphabetic characters are ascending (e.g., the code for "A" is 65 and the code for "Z" is 90). Unlike the relational equality operator (=) , true (.T.) is returned if exp1 and exp2 are exactly equal including trailing spaces; otherwise, the comparison returns false (.F.). SET EXACT has no effect.
■ Date: Dates are compared according to the underlying date
value; behaves the same as the relational equality operator (=).
■ Logical: True (.T.) is exactly equal to true (.T.), and false
(.F.) is exactly equal to false (.F.).
■ Memo: Treated the same as character.
■ NIL: True (.T.) if compared to a NIL value; false (.F.) if
compared to a value of any other data type.
■ Numeric: Compared based on magnitude; behaves the same as the
relational equality operator (=).
■ Object: Treated the same as array.
Examples
■ These examples illustrate how the == operator behaves with
different data types:
// Character
? "A" == "A" // Result: .T.
? "Z" == "A" // Result: .F.
? "A" == "A " // Result: .F.
? "AA" == "A" // Result: .F.
// Array or object
aOne := { 1, 2, 3 }
aTwo := { 1, 2, 3 }
aThree := aOne
? aOne == aTwo // Result: .F.
// values within the arrays are equal, but the arrays,
// themselves, are separate and distinct
? aOne == aThree // Result: .T.
The greater than or equal to operator (>=) is a binary operator that compares two values of the same data type and returns true (.T.) if exp1 is greater than or equal to exp2.
■ Character: The comparison is based on the underlying ASCII
code. ASCII codes for alphabetic characters are ascending (e.g., the code for "A" is 65 and the code for "Z" is 90).
■ Date: Dates are compared according to the underlying date
value.
■ Logical: True (.T.) is greater than false (.F.).
■ Memo: Treated the same as character.
■ Numeric: Compared based on magnitude.
Examples
■ These examples illustrate how the greater than or equal
operator (>=) behaves with different data types:
// Character
? "Z" >= "A" // Result: .T.
? "AZ" >= "A" // Result: .T.
? "A" >= "AZ" // Result: .F.
// Date
? CToD("12/12/88") >= ;
CToD("12/11/88") // Result: .T.
// Logical
? .T. >= .F. // Result: .T.
// Numeric
? 2 >= 1 // Result: .T.
? 1 >= 2 // Result: .F.
? 2 >= 2 // Result: .T.
The (-) operator performs different operations depending on the data types of the operands:
■ Unary negative sign (numeric): A numeric expression prefaced
with the minus (-) operator performs the equivalent of multiplying the operand by (-1), returning a negative numeric value.
■ Binary subtraction (numeric, date): If both operands are
numeric data type, nNumber2 is subtracted from nNumber1 and the result is returned as a numeric value. If both operands are date data type, dDate2 is subtracted from dDate1 and the result is returned as a numeric value representing the number of days between the two dates. If the left operand is date data type and the right operand numeric data type, the nNumber is subtracted as days from dDate and a date value is returned. If the order of operands is reversed, a runtime error occurs.
■ Concatenation (character, memo): If both operands are
character data type, cString2 is joined to cString1, returning a character string. Trailing blanks are trimmed from cString1 and joined to the end of the return string.
When used with an idAlias as the first operand, the alias operator
(->) accesses field information or evaluates an expression in the indicated work area. The alias operator implicitly SELECTs the idAlias before evaluating the idField or exp operand. When the evaluation is complete, the original work area is SELECTed again. An alias reference can be in an expression or on a line by itself:
? Customer->Name Customer->(UpdateTransaction())
Using the alias operator lets you:
■ Access information from unselected work areas within
expressions
■ Access environmental information from unselected work areas
■ Access information from unselected work areas in modes such as
REPORT and LABEL FORMs
■ Write more compact code
In addition to allowing expression and field evaluation in unselected work areas, the alias operator makes an explicit reference to a field or variable using either the FIELD or the MEMVAR keyword aliases. MEMVAR forces idVar to refer to a memory variable name, and FIELD forces it to reference a database field. These special alias identifiers allow you to avoid ambiguity when there are conflicts between field and memory variable names. Remember that a reference to a variable identifier not prefaced with an alias defaults to a field if there are both field and memory variables with the same name. To override this, use the (/V) option when compiling.
In addition to specifying the alias as an identifier, you can access the target work area using an expression that returns the work area number if the expression is enclosed by parentheses. This lets you use work area numbers as handles, which is useful for passing references to work areas without using macros, aliases, names, etc.
Examples
■ This example accesses database and work area information in an
unselected work area:
USE Customer NEW
USE Invoices NEW
? Customer->CustName // Result: Bill Smith
? Customer->(RecNo()) // Result: 1
? Customer->(Found()) // Result: .F.
? Customer->(City + ", " + State + ;
" " + Zip) // Result: ShadowVille,
// CA 90415
■ This example uses a user-defined function (MySeek()) as an
operand of the alias operator for a common operation that normally
requires many more statements:
IF Invoices->(MySeek(CustNum))
<process customer>...
ELSE
<process no find>...
ENDIF
RETURN
FUNCTION MySeek( cSearch )
SEEK cSearch
RETURN (Found())
Note: This example is just an illustration of the alias operator
with a user-defined function. CA-Clipper's dbSeek() could be used
instead of MySeek().
■ This example explicitly references field and memory variables
with the same name:
USE Customer NEW
MEMVAR->CustName = "Bill Smith" // Create a memvar
// CustName
LOCATE FOR MEMVAR->CustName = FIELD->CustName
■ This example uses an expression as a work area handle to
create a work area-independent database operation:
cTable1 := "C:Myfile.dbf"
cTable2 := "D:Myfile.dbf"
USE (cTable1) NEW
hArea1 = Select()
USE (cTable2) NEW
hArea2 = Select()
DoStuff( hArea1, hArea2 )
FUNCTION DoStuff( hArea1, hArea2 )
LOCAL nCount, nSave
nSave := Select()
SELECT (hArea1)
FOR nCount := 1 TO FCount()
FieldPut( nCount, ( hArea2 )-> ;
( FieldGet( nCount )))
NEXT
SELECT (nSave)
RETURN NIL
The decrement operator (—) decreases the value of its operand by one. This operator subtracts one from the value of idVar and assigns the new value to idVar.
The — operator can appear before or after idVar. Specifying the operator before idVar decrements and assigns the value before the value is used. This is called prefix notation, and it is the most common usage. Specifying the operator after idVar decrements and assigns the value after it is used. This is postfix notation. Stated differently, postfix notation delays the assignment portion of the operation until the rest of the expression is evaluated, and prefix notation gives the assignment precedence over all other operations in the expression.
If the reference to idVar is ambiguous (i.e., not declared at compile time and not explicitly qualified with an alias), idVar is always assumed to be MEMVAR. You can assign field variables by declaring the field variable name in a FIELD statement or by referring to the field name prefaced by the FIELD-> alias or by the name of the work area.
Examples
■ In this example of the postfix decrement operator the
assignment takes place before the original variable is decremented,
thus the two values are not the same when queried:
nValue := 1
nNewValue := nValue--
? nNewValue // Result: 1
? nValue // Result: 0
■ In this example, the prefix decrement operator decreases the
first operand of the multiplication by one, making its value 9.
Then, the assignment of this new value to the nValue variable takes
place before the rest of the expression is evaluated. Thus, the new
value is used to perform the multiplication operation, and the result
of 9 * 9 is 81.
nValue := 10
? --nValue * nValue // Result: 81
? nValue // Result: 9
Each class defines a set of operations that can be performed on objects of that class. Perform these operations by sending a message to the object using the send operator (:).
When a message is sent to an object, the system examines the message. If the object is of a class that defines an operation for that message, the system automatically invokes a method to perform the operation on the specified object. If the class does not define a method for the specified message, a runtime error occurs.
Executing a message send produces a return value, much like a function call. The return value varies depending on the operation performed.
Examples
■ In this example, myBrowse is the name of a variable that
contains a TBrowse object reference. pageUp() is a method that
specifies the operation to be performed. The available operations
and corresponding methods vary depending on the class of the object.
The Error, Get, TBColumn, and TBrowse classes are documented in this
chapter.
myBrowse:pageUp()
■ This example forces the checkbox state to true (.T.):
myCheck : Select (.T.)
The inline assignment operator (:=) assigns values of any data type to variables of any storage class. The operator evaluates exp, assigns the resulting value to idVar, and returns the resulting value as the return value of the operation. This latter behavior permits multiple assignments such as idVar1 := idVar2 := value. Unlike the simple assign operator (=), the inline assignment operator (:=) can be used anywhere an expression or constant is allowed, including variable declaration statements. With a variable declaration statement, assignment initializes a variable. Note, however, you cannot declare an array and initialize elements within the same program statement.
If the reference to idVar is ambiguous (i.e., not declared at compile time and not explicitly qualified with an alias), idVar is always assumed to be MEMVAR. At runtime, if no private or public variable exists with the specified name, a private variable is created. You can assign field variables with the := operator by declaring the field variable name in a FIELD statement or referring to the field name prefaced by the FIELD-> alias or the name of the work area.
Examples
■ Several examples of inline assignment follow:
LOCAL nValue := 10
//
IF (dDate := (Date() - 1000)) = CToD("12/20/79")
//
? Sqrt(nValue := (nValue ** 2))
//
cTransNo := cSortNo := (CustId + DToC(Date()))
■ This last example performs multiple assignments using the
inline assignment operator as you would with the STORE command. When
:= is used in this way, the assignments are executed from right to
left. This feature is particularly useful when you need to store the
same value to many different fields, possibly in different database
files.
CustFile->CustId := TransFile-> ;
TransNo := (CustId + DToC(Date())
exp list is a list of values to display and can be any combination of data types, including memo.
If you specify no argument and use the ? command, a carriage return/linefeed is sent to the console. If you use the ?? command without arguments, nothing happens.
Description
? and ?? are console commands that display the results of one or more expressions, separated by a space, to the console. These commands are also command synonyms for the QOut() and QQOut() functions, respectively.
Although functionally similar, ? and ?? differ slightly. ? sends a carriage return/linefeed to the console before displaying the results of the expression list. ?? displays output at the current screen cursor or printhead position. This lets you use successive ?? commands to display output to the same line.
A ? or ?? command locates the cursor or printhead one position to the right of the last character displayed. If SET PRINTER is OFF, Row() and Col() are updated to reflect the new cursor position. If SET PRINTER is ON, PRow() and PCol() are updated with the new printhead position.
If output from a ? or ?? command reaches the edge of the screen as reported by MaxCol(), it wraps to the next line. If the output reaches the bottom of the screen as reported by MaxRow(), the screen scrolls up one line.
You can echo output from the ? or ?? commands to the printer by specifying a SET PRINTER ON command before beginning output. You can echo output from both of these commands to a text file using SET ALTERNATE TOxcFile to create the file, and SET ALTERNATE ON to begin echoing to the file. Like other console commands, SET CONSOLE OFF suppresses the display to the screen without affecting output to the printer or text file.
To format any expression specified, use Transform() or a user-defined function. If you need to pad a variable length value for column alignment, use any of the Pad() functions to left-justify, right- justify, or center the value. See the examples below.
Examples
■ This example prints a record from a database file using ? and
?? commands with PadR() to ensure column alignment:
LOCAL nPage := 0, nLine := 99
USE Salesman INDEX Salesman NEW
SET PRINTER ON
SET CONSOLE OFF
DO WHILE !Eof()
IF nLine > 55
IF nPage != 0
EJECT
ENDIF
? PadR("Page", LTrim(Str(nPage++)), 72)
?? DToC(Date())
?
?
? PadC("Sales Listing", 79)
?
nLine := 5
ENDIF
? Name, Address, PadR(RTrim(City) + "," ;
+ State, 20), ZipCode
nLine++
SKIP
ENDDO
SET CONSOLE ON
SET PRINTER OFF
CLOSE Salesman
The .AND. operator is a binary logical operator that executes a logical AND operation using the following modified Boolean rules:
■ Returns true (.T.) if both lCondition1 and lCondition2
evaluate to true (.T.)
■ Returns false (.F.) if either lCondition1 and lCondition2
evaluate to false (.F.)
Warning! In a departure from Summer '87 and other dialect behavior, CA-Clipper shortcuts the evaluation of .AND. operands. This means that lCondition1 and lCondition2 are both evaluated only when lCondition1 evaluates to TRUE (.T.). If lCondition1 evaluates to FALSE (.F.), the .AND. operation is FALSE (.F.) and lCondition2 is therefore not evaluated.
For backward compatibility, shortcutting can be suppressed by compiling with the /Z option.
Examples
■ This example shows .AND. results using different operands:
? .T. .AND. .T. // Result: .T.
? .T. .AND. .F. // Result: .F.
? .F. .AND. .T. // Result: .F. (shortcut)
? .F. .AND. .F. // Result: .F. (shortcut)
The .OR. operator is a binary logical operator that executes a logical OR operation using the following modified Boolean rules:
■ Returns true (.T.) if either lCondition1 or lCondition2
evaluates to true (.T.)
■ Returns false (.F.) if both lCondition1 and lCondition2
evaluates to false (.F.)
Warning! In a departure from the Summer '87 and other dialect behavior, CA-Clipper shortcuts the evaluation of .OR. operands. This means that lCondition1 and lCondition2 are both evaluated only when lCondition1 evaluates to false (.F.). If lCondition1 evaluates to true (.T.), the .OR. operation is true (.T.) and lCondition2 is, therefore, not evaluated. For backward compatibility, shortcutting can be suppressed by compiling with the /Z option.
Examples
■ This example shows .OR. results using different operands:
? .T. .OR. .T. // Result: .T. (shortcut)
? .T. .OR. .F. // Result: .T. (shortcut)
? .F. .OR. .T. // Result: .T.
? .F. .OR. .F. // Result: .F.
Parentheses (()) in expressions are used to group certain operations for readability or to force a particular evaluation order. Parentheses also identify a function call.
When specifying the grouping operator, the item that falls within the parentheses must be a valid expression. Subexpressions may be further grouped.
For function calls, a valid function name must precede the left parenthesis, and the function arguments, if any, must be contained within the parentheses.
Examples
■ This example changes the default order of expression
evaluation:
? 5 * (10 + 6) / 2 // Result: 40
■ The next example shows a function call:
x := Sqrt(100)
The subscript operator ([]) specifies a single array element. The name of a previously declared array must precede the left bracket and the array element subscript must appear as a numeric expression within the brackets. You can make array element references using Pascal or C-style syntax.
Examples
■ This example accesses each element in a two-dimensional array
of known dimensions:
LOCAL i, j
FOR i := 1 TO 5
FOR j := 1 TO 10
? aOne[i, j]
NEXT
NEXT
■ These examples specify an <aArray> expression:
LOCAL aArray := { 1, 2, 3, 4, 5 }
//
? ArrayFunc()[2] // Result: 2
? { {1, 2}, {3, 4} }[1][2] // Result: 2
? aArray[5] // Result: 5
FUNCTION ArrayFunc
STATIC aArray := { 1, 2 }
RETURN aArray
■ This example queries and assigns a static array encapsulated
within a function definition:
? ArrayFunc()[1] // Result: 1
ArrayFunc()[1] := 10
? ArrayFunc()[1] // Result: 10
FUNCTION ArrayFunc
STATIC aArray := { 1, 2 }
RETURN aArray
Curly braces ({}) delimit references to literal arrays or code blocks. If the reference is a literal array, you can use them to create an array in either an assignment or a variable declaration statement. If the reference is a variable declaration, the array can contain expressions of any kind as elements, unless STATIC is the declaration statement. In this case, the literal array can only contain constant values.
Examples
■ This example uses literal arrays in declaration statements to
create a variable and initialize it with an array reference:
LOCAL aPerson := { "Name", "Address", Date() }
STATIC aNumList := { 1, 2, 3, 4, 5, 6, 7, 8 }
■ This example creates a multidimensional literal array:
aMulti := { {1, 2, 3}, {"A", "B", "C"} }
■ This example uses curly braces to formulate a simple code
block with a single parameter:
LOCAL bSayBlock
bSayBlock := { |x| QOut(x) }
Eval(bSayBlock, 10) // Result: 10
The pass-by-reference operator (@) passes variables by reference to functions or procedures invoked with function-calling syntax. It is a unary prefix operator whose operand may be any variable name.
Passing a variable by reference means that a reference to the value of the argument is passed instead of a copy of the value. The receiving parameter then refers to the same location in memory as the argument. If the called routine changes the value of the receiving parameter, it also changes the argument passed from the calling routine.
Passing a variable by value means that the argument is evaluated and its value is copied to the receiving parameter. Changes to a receiving parameter are local to the called routine and lost when the routine terminates. The default method of passing arguments is by value for all data types including references to arrays and objects.
Examples
■ This example demonstrates the difference between passing a
user-defined function argument by reference and by value:
LOCAL nNum := 1 // Initial values
LOCAL aArr := { "a", "b", "c" }
//
CLS
// Print initial values
? ValType(nNum), nNum
? ValType(aArr), aArr[1], aArr[2], aArr[3]
//
Udf1(nNum) // Pass by value (default)
? ValType(nNum), nNum // Result: N, 1
//
Udf1(aArr[1]) // Pass by value (default)
? ValType(aArr), aArr[1],;
aArr[2], aArr[3] // Result: A, "a" "b" "c"
//
Udf2(aArr) // Pass a reference to
? ValType(aArr), aArr[1],; // the array (default)
aArr[2], aArr[3] // A, "Oi!" "b" "c"
//
Udf1(@nNum) // Force pass by reference
? ValType(nNum), nNum // Result: N, 1000
//
Udf3(@aArr) // Pass array by reference
? ValType(aArr) // Result: N
//
RETURN NIL
FUNCTION Udf1(nParam) // Receive as a local
? nParam // parameter
nParam := 1000
? nParam
RETURN NIL
//
FUNCTION Udf2( aParam ) // Receive as a local
? ValType(aParam), aParam[1] // parameter
aParam[1] := "Oi!"
? aParam[1]
RETURN NIL
//
FUNCTION Udf3(aParam) // Receive as a local
? ValType(aParam), aParam[1] // parameter
aParam := 1000
? aParam
RETURN NIL
nTop, nLeft, nBottom, nRight define the coordinates of the box. @...BOX draws a box using row values from zero to MaxRow(), and column values from zero to MaxCol(). If nBottom and nRight are larger than MaxRow() and MaxCol(), the bottom-right corner is drawn off the screen.
BOX cBoxString defines a string of eight border characters and a fill character. If cBoxString is specified as a single character, that character draws the whole box.
COLORcColorString defines the display color of the drawn box. If not specified, the box is drawn using the standard color setting of the current system color as defined by SetColor(). Note that cColorString is a character expression containing the standard color setting. If you want to specify a literal color setting, enclose it within quote marks.
Description
@...BOX draws a box on the screen using configurable border and fill characters. @...BOX draws the box using cBoxString starting from the upper left-hand corner, proceeding clockwise and filling the screen region with the ninth character. If the ninth character is not specified, the screen region within the box is not painted. Existing text and color remain unchanged.
After @...BOX executes, the cursor is located in the upper corner of the boxed region at nTop + 1 and nLeft + 1. Row() and Col() are also updated to reflect the new cursor position.
Examples
■ These examples draw two boxes using box manifest constants
defined in the supplied header file, box.ch. The first example draws
a box using the specified characters for the border, but leaves all
other areas of the screen intact. The second example draws the same
box filling the box region with space characters.
#include "Box.ch"
// Draw a box with a double-line top with a
// single-line side
@ 1, 1, 22, 79 BOX B_DOUBLE_SINGLE
// Draw the same box filling the box region with
// spaces
@ 1, 1, 22, 79 BOX B_DOUBLE_SINGLE + Space(1)
nTop and nLeft define the upper-left corner coordinate.
TOnBottom, nRight defines the lower-right corner coordinates of the screen region to CLEAR. If the TO clause is not specified, these coordinates default to MaxRow() and MaxCol().
Description
@...CLEAR erases a rectangular region of the screen by filling the specified region with space characters using the current standard color setting. After @...CLEAR erases the designated region, the cursor is located in the upper corner of the region at nTop + 1 and nLeft + 1. Row() and Col() are also updated to reflect the new cursor position.
Examples
■ This example erases the screen from 10, 10 to 20, 40, painting
the region blue and then displaying a bright cyan box on blue:
SetColor("BG+/B")
@ 10, 10 CLEAR TO 20, 40
@ 10, 10 TO 20, 40
nRow and nCol specify the row and column coordinates for the operation. If the SAY clause is present, nRow and nCol specify the coordinates for the SAY, and the GET is displayed to the right of the SAY output. If the SAY clause is not present, nRow and nCol directly specify the coordinates for the GET. In either case, output which extends beyond the visible extent of the display is clipped and does not appear.
SAYexp displays the value of exp at the specified coordinates. If you specify the PICTUREcSayPicture clause, exp is formatted according to the rules of SAY pictures.
GETidVar specifies the name of the variable associated with the GET. idVar may be of any storage class (if the storage class is ambiguous, FIELD is assumed). If idVar contains an array value, you must supply one or more subscripts. The current value of idVar is displayed at the GET coordinates. The value must be character, date, numeric, or logical type. Array, NIL, code block, and null string values are not permitted.
PICTUREcGetPicture specifies the display format and editing rules for the GET.
COLORcColorString defines the color settings for the current Get object. cColorString is a character expression containing one or more color settings. You must specify literal color settings enclosed in quote marks.
If you specify two color settings, the first determines the unselected color (the display color for the Get object) and the second determines the selected color (the color when the Get object has focus). If you only specify one color, it determines both the unselected and selected colors for the Get object.
On a combined @...SAY...GET command, two COLOR clauses are required to specify colors for both the SAY and the GET: one for the SAY, and one for the GET.
CAPTIONcCaption specifies a character string that concisely describes the GET on the screen. Caption differs from the SAY argument in two ways. The first is that the caption is displayed each time the GET is shown on the screen. The other difference is that the caption, along with its screen position, is maintained within the Get object. This allows the GET to receive input when the mouse's left button is clicked and its cursor is on the caption. By default, the caption appears to the right of the GET. Use the Get object's capRow or capCol variable to change the screen position of the caption. Note that if the SAY clause is used, the CAPTION clause is ignored.
When present, the & character specifies that the character immediately following it in the caption is the GET's accelerator key. The accelerator key provides a quick and convenient mechanism for the user to move input focus from one data input control to the GET. The user performs the selection by pressing the Alt key in combination with an accelerator key. The case of an accelerator key is ignored.
MESSAGEcMessage specifies a character string that is displayed on the Get system's status bar line when the GET has input focus. Typically, it describes the anticipated contents or user response of the GET. Refer to the SET MESSAGE command for details pertaining to the Get system's status bar.
WHENlPreExpression specifies an expression that must be satisfied before the cursor can enter the GET during a READ. The expression can optionally be a code block. The Get object is passed as a parameter to the code block.
RANGE* dnLower, dnUpper specifies a range of allowable values for input to the GET. During a READ command, if you enter a new GET value that does not fall within the specified range, the cursor cannot leave the GET.
VALIDlPostExpression specifies an expression that must be satisfied before the cursor can leave the GET during a READ. The expression can optionally be a code block. The Get object is passed as a parameter to the code block.
SENDmsg sends the specified message to the Get object. msg is sent before the GET is displayed. Any message can be sent, including method calls and instance variable assignments. Method calls must include parentheses even if no arguments are passed.
GUISENDguimsg can be used to send a message (such as the Display() method) to a GUI object. The GUI objects available in CA-Clipper are check boxes, list boxes, push buttons, and radio button groups. To send a message to a non-GUI object, such as standard GETs and TBrowses, use the SEND clause.
Description
The @...GET command creates a new Get object, displays its value, and adds it to the array referred to by the variable GetList. If no variable called GetList has been declared or created in the current procedure, and no PRIVATE variable called GetList exists from a previous procedure, the system uses the predefined PUBLIC variable GetList. A subsequent READ command activates the GETs contained in the GetList array and allows the user to edit their contents.
Each Get object has an associated variable, idVar. The variable may be of any storage class, including a database field, private, public, local, or static variable. If idVar is followed by one or more subscripts, the specified array element is associated with the GET. When the Get object is created, the idVar name is stored in the Get object, along with a code block which allows the value of idVar to be retrieved or assigned during the READ.
The READ command performs a full-screen edit of the GETs in the GetList array. As the user moves the cursor into each GET, the value of the associated idVar is retrieved by evaluating the code block saved in the Get object. The value is converted to textual form and placed in a buffer within the Get object. This buffer is displayed on the screen, and the user is allowed to edit the text from the keyboard. When the user moves the cursor out of the GET, the updated buffer is converted back to the appropriate data type and assigned to idVar.
Automatic formatting and validation: During a READ, some formatting and edit validation is automatically performed for numeric, date, and logical values. As the user is typing, an automatic data type test is performed on each key pressed, preventing the user from entering an invalid character.
Prevalidation: The WHEN clause specifies a condition which must be satisfied before the cursor can enter the GET. During a READ, lPreExpression is evaluated whenever the user attempts to move the cursor into the GET. If it evaluates to true (.T.), the cursor can enter; otherwise, the GET is skipped.
Postvalidation: You may perform postvalidation using either the VALID or RANGE* clauses. VALID specifies a condition which must be satisfied before the cursor can leave the GET. During a READ, lPostExpression is evaluated whenever the user attempts to move the cursor out of the GET. If it evaluates to true (.T.), the cursor can leave; otherwise, the cursor remains in the GET. RANGE* specifies a range of acceptable values for numeric or date values. If the value entered by the user is not within the specified range, the cursor cannot leave the GET.
Note: You may specify either a VALID or RANGE clause, but not both.
PICTURE: When you specify the PICTURE clause for a GET, the character string specified by cGetPicture controls formatting and edit validation. The picture string controls the display format like a SAY picture. It also controls the way the user can edit the buffer. A picture string consists of two distinct parts, a function string and a template string, either or both of which may be present.
■ Function string: A PICTURE function string specifies
formatting or validation rules which apply to the GET's display value as a whole, rather than to particular character positions within it. The function string consists of the @ character, followed by one or more additional characters, each of which has a particular meaning (see the following table). The function string must be the first element of a PICTURE clause and cannot contain spaces. A function string may be specified alone or with a template string. If both are present, the function string must precede the template string, and the two must be separated by a single space.
GET PICTURE Format Functions
Function Type Action
A C Allows only alphabetic characters.
B N Displays numbers left-justified.
C N Displays CR after positive numbers.
D D,N Displays dates in SET DATE format.
E D,N Displays dates with day and month inverted
independent of the current DATE SETting, numerics
with comma and period reverse (European style).
K ALL Deletes default text if first key is not a cursor
key.
R C Nontemplate characters are inserted in the display
but not saved in the variable.
S<n> C Allows horizontal scrolling within a GET. <n> is
an integer that specifies the width of the region.
X N Displays DB after negative numbers.
Z N Displays zero as blanks.
( N Displays negative numbers in parentheses with
leading spaces.
) N Displays negative numbers in parentheses without
leading spaces.
! C Converts alphabetic character to uppercase.
■ Template string: A PICTURE template string specifies
formatting or validation rules on a character by character basis. The template string consists of a series of characters, some of which have special meanings (see the following table). Each position in the template string corresponds to a position in the displayed GET value. Characters in the template string that do not have assigned meanings are copied verbatim into the displayed GET value. If you use the @R picture function, these characters are inserted between characters of the display value, and are automatically removed when the display value is reassigned to idVar; otherwise, they overwrite the corresponding characters of the display value and also affect the value assigned to idVar. You may specify a template string alone or with a function string. If you use both, the function string must precede the template string, and the two must be separated by a single space.
GET PICTURE Template Symbols
Template Action
A Allows only alphabetic characters
N Allows only alphabetic and numeric characters
X Allows any character
9 Allows digits for any data type including sign for
numerics
# Allows digits, signs and spaces for any data type
L Allows only T, F, Y or N
Y Allows only Y or N
! Converts an alphabetic character to uppercase
$ Displays a dollar sign in place of a leading space in a
numeric
* Displays an asterisk in place of a leading space in a
numeric
. Displays a decimal point
, Displays a comma
SCOREBOARD: If a new value is rejected because it fails the RANGE* test or because it is a malformed date value, a message appears on the screen. The message displays in the SCOREBOARD area, which you can enable or disable using the SET SCOREBOARD command.
Exit with Esc: If the user exits a GET by pressing Esc, the GET variable is restored to the value it had on entry to the GET, and the READ is terminated. No postvalidation is performed. You can enable or suppress this behavior with the SET ESCAPE command.
SET KEY procedures: The SET KEY command lets you specify a procedure to be executed whenever a specific key is pressed during a READ. After a SET KEY procedure terminates, the GET is reactivated with the cursor restored to its previous position.
Lifetime of a Get object: Get objects, like arrays, exist as long as there are active references to them somewhere in the current program. Normally, only the array in the GetList variable maintains a reference to the Get object; the GET is released when GetList is released or reassigned. The CLEAR and CLEAR GETS commands assign an empty array to GetList, as does the READ command unless you specify the SAVE clause.
Assignment: Each GET is associated with a variable, idVar, in the @...GET command. At various times during the editing process, idVar may be assigned the current value of the Get object's buffer. This occurs in the following instances:
■ After the user presses an exit key and before the validation
expression is executed
■ After the user presses a SET KEY
Also, the current Get object's buffer is refreshed from idVar and redisplayed at various intervals:
■ After a SET KEY procedure terminates
■ After a WHEN expression is evaluated
■ After a VALID expression is evaluated
This lets you explicitly assign idVar within any of these operations. See the note below for more information.
GET coordinates and display: When you create a Get object using the @...GET command, the row and column coordinates at which the GET is initially displayed are stored in the Get object. When the @...GET command executes, the new GET displays at nRow and nCol, unless you specify the SAY clause which positions the GET so there is one display column between the last character of the SAY output and the first character of the GET (or of the DELIMITERS, see below).
If SET DELIMITERS is ON when the @...GET command executes, the current DELIMITER characters display on either side of the initial GET display, and the column coordinate of the GET is adjusted accordingly. Note that the delimiters are not attributes of the Get object, but simply display as the SAY clause does.
If INTENSITY is ON, GETs initially display in the current unselected color (or the enhanced color, if no unselected color has been specified). During a READ, the active GET displays in the enhanced color, while the remaining GETs display in the unselected color. With INTENSITY OFF, all GETs display in the standard color.
When a GET displays, the width of the displayed value is determined by the length of the value in idVar or, if you specify the PICTURE clause, by the number of positions in cGetPicture. If you specify the @S function as a part of cGetPicture, the @S argument controls the width of the displayed value.
Notes
■ WHEN and VALID: The expressions specified in the WHEN and
VALID clauses may be of arbitrary complexity and may include calls to user-defined functions. This is useful for attaching automatic actions to the activation or deactivation of a GET.
■ Assigning idVar: Because of the automatic refresh and
display properties of a Get object while it is being READ, you can make an explicit assignment to the Get object's idVar within a WHEN or VALID expression. You can directly assign the variable by name in the validation expression or, for private, public, local, or static variables, by passing a reference to idVar to a function; the function can then assign idVar by assigning the corresponding formal parameter. If idVar is a field, it is globally visible and can be assigned by name in a function called by the validation expression.
When including a GET in a called function, do not include an idVar with the same name as a field idVar. Field references have precedence over public variables so the public idVar will be ignored.
■ GET specific help: You can use a SET KEY procedure to display
help text associated with a Get object. Within the SET KEY procedure, use the ReadVar() function to determine the idVar associated with the current Get object. Use this information to display the appropriate help text. Remember that when a CA-Clipper- compiled program loads, the F1 KEY is automatically SET TO a procedure or user-defined function named Help.
■ SET DEVICE TO PRINTER: SET DEVICE TO PRINTER does not direct
display of a Get object under the @...GET command to the printer or file.
Examples
■ This example uses the VALID clause to validate input into a
GET:
LOCAL nNumber := 0
@ 10, 10 SAY "Enter a number:" ;
GET nNumber VALID nNumber > 0
■ This example demonstrates passing a code block with the VALID
clause. The parameter oGet is the current Get object. Udf() changes
the value of the GET:
LOCAL GetList := {}, cVar := Space(10)
CLS
@ 10, 10 GET cVar VALID { |oGet| Udf1( oGet ) }
READ
.
.
.
* Udf( <oGet> ) --> .T.
FUNCTION Udf1( oGet )
IF "test" $ oGet:BUFFER // Compare buffer contents
oGet:varPut( "new value " ) // Change contents
ENDIF
RETURN .T.
■ This example uses the WHEN clause to prohibit entry into GETs
based on the value of another GET. In this example, entering Y in the
Insured field indicates the client has insurance and the user is
allowed to enter insurance information. If the client does not have
insurance, the cursor moves to the Accident field:
@ 10, 10 GET Insured PICTURE "Y"
@ 11, 10 GET InsNumber WHEN Insured
@ 12, 10 GET InsCompany WHEN Insured
@ 13, 10 GET Accident PICTURE "Y"
READ
■ This is an example of a GET in a secondary work area:
USE Invoice NEW
APPEND BLANK
USE Inventory NEW
@ 1, 1 GET Invoice->CustNo
READ
■ This example uses the @K function to suggest a default input
value, but deletes it if the first key pressed is not a cursor key or
Return:
LOCAL cFile := "Accounts"
@ 1, 1 SAY "Enter file" GET cFile PICTURE "@K"
READ
■ This is an example of a nested READ using a GetList and
lexical scoping:
#include "inkey.ch"
//
// Local to this function only
LOCAL GetList := {}
LOCAL cName := Space( 10 )
//
CLS
SetKey( K_F2, { || MiscInfo() } ) // Hot key to special READ
//
// Get object added to getlist
// works on local getlist
@ 10, 10 SAY "Name" GET cName
READ
//
RETURN NIL
/***
* MiscInfo() ---> NIL
*/FUNCTION MiscInfo()
//
LOCAL GetList := {} // Local to this
LOCAL cExtraInfo := Space( 30 ) // function only
//
// Get object added to getlist
// works on local getlist
@ 12, 10 SAY "Note: " GET cExtraInfo
READ
//
RETURN NIL
nRow and nCol specify the row and column coordinates for the check box and its caption. Output which extends beyond the visible extent of the display is clipped and does not appear.
GETlVar specifies the name of the variable associated with the GET. lVar must contain a logical value. A value of true (.T.) indicates that the check box is checked; otherwise, a value of false (.F.) indicates that it is not checked.
CAPTIONcCaption specifies a character string that concisely describes the GET on the screen. Caption differs from the SAY argument in two ways. The first is that the caption is displayed each time the GET is shown on the screen. The other difference is that the caption, along with its screen position, is maintained within the Get object. This allows the GET to receive input when the mouse's left button is clicked and its cursor is on the caption. By default, the caption appears to the left of the GET. Use the Get object's capRow or capCol variable to change the screen position of the caption.
When present, the & character specifies that the character immediately following it in the caption is the check box's accelerator key. The accelerator key provides a quick and convenient mechanism for the user to move input focus from one data input control to the check box. The user performs the selection by pressing the Alt key in combination with an accelerator key. The case of an accelerator key is ignored.
MESSAGEcMessage specifies a character string that is displayed on the Get system's status bar line when the GET has input focus. Typically, it describes the anticipated contents or user response of the GET. Refer to the READ command for details pertaining to the Get system's status bar.
WHENlPreExpression specifies an expression that must be satisfied before the cursor can enter the GET during a READ. The expression can optionally be a code block. The Get object is passed as a parameter to the code block.
VALIDlPostExpression specifies an expression that must be satisfied before the cursor can leave the GET during a READ. The expression can optionally be a code block. The Get object is passed as a parameter to the code block.
COLORcColorString defines the color settings for the check box. cColorString is a character expression containing exactly four color settings.
CheckBox Color Attributes
Position Applies To Default Value from
in colorSpec System Color Setting
1 The check box when it does not have Unselected
input focus
2 The check box when it has input focus Enhanced
3 The check box's caption Standard
4 The check box caption's accelerator key Background
Note: In graphic mode, colorSpec positions 1 and 2 have no affect and are ignored.
FOCUSfblock specifies a code block that is evaluated each time the check box receives focus. The code block takes no implicit arguments. Use the CheckBox:hasFocus instance variable to determine if the check box has focus.
STATEbBlock specifies a code block that is evaluated each time the check box's state changes. The code block takes no implicit arguments. Use the CheckBox:buffer instance variable to determine if the check box is being checked or unchecked. A value of true (.T.) indicates that it is being checked; otherwise, a value of false (.F.) indicates that it is being unchecked.
STYLEcStyle specifies a character string that indicates the check box's delimiter characters. The string must contain four characters. The first is the left delimiter. Its default value is the left square bracket ([) character. The second is the checked indicator. Its default value is the square root
() character. The third is the unchecked indicator. Its default is
the space character (" "). The fourth character is the right delimiter. Its default value is the right square bracket (]) character.
Note: The style clause is ignored in graphic mode.
SENDmsg sends the specified message to the Get object. msg is sent before the GET is displayed. Any message can be sent, including method calls and instance variable assignments. Method calls must include parentheses even if no arguments are passed.
GUISENDguimsg can be used to send a message (such as the Display() method) to a GUI object. The GUI objects available in CA-Clipper are check boxes, list boxes, push buttons, and radio button groups. To send a message to a non-GUI object, such as standard GETs and TBrowses, use the SEND clause.
BITMAPSaBitmaps contains an array of exactly two elements. The first element of this array is the file name of the bitmap to be displayed when the check box is selected. The second element of this array is the file name of the bitmap to be displayed when the check box is not selected.
Drive and directory names are not allowed; the file name extension is required. A bitmap file can be stored as a file on disk or in a bitmap library. If stored as a file, the file must reside in the same directory as the application. If stored in a bitmap library, the library must reside in the same directory as the application and it also must have the same name as the application with a .bml extension.
CA-Clipper will search for the file name first and, if it is not found, search in the bitmap library second. If no file is found either on disk or in the library, no bitmap will be displayed.
This argument only affects applications running in graphic mode and is ignored in text mode.
Examples
■ This example demonstrates how to add a check box to a data entry screen:
@ 5, 20 GET lReadOnly CHECKBOX
■ This example demonstrates a check box that has a caption and a
message:
@ 5, 20 GET lReadOnly CHECKBOX ;
CAPTION "&Read Only" ;
MESSAGE "Check to open file for reading only"
■ This example demonstrates a check box that uses the X
character as the checked character instead of the square root
character.
@ 5, 20 GET lReadOnly CHECKBOX ;
CAPTION "&Read Only" ;
MESSAGE "Check to open file for reading only" ;
STYLE "[X ]"
nTop, nLeft, nBottom and nRight specify the screen position for the list box and its caption. Output which extends beyond the visible extent of the display is clipped and does not appear.
GETnVar|cVar specifies the name of the variable associated with the GET. Its value indicates which item (if any) in the list is selected. A numeric value refers to the position in the list of the selected item. A value of 0 indicates no selected item. A character string value refers to the data or text contained within the selected item. A character string that does not refer to any item in the list indicates no selected item.
LISTBOXaList specifies an array that contains the items in the list. The array may be either a single- or two-dimensional array. Use a single-dimension array when the data being displayed is the same as the data being saved; otherwise, use a two-dimensional array. In this case, the data in the first element of each subarray is displayed and the data in the second element is used for determining which item is selected.
CAPTIONcCaption specifies a character string that concisely describes the GET on the screen. Caption differs from the SAY argument in two ways. The first is that the caption is displayed each time the GET is shown on the screen. The other difference is that the caption, along with its screen position, is maintained within the Get object. This allows the GET to receive input when the mouse's left button is clicked and its cursor is on the caption. By default, the caption appears to the left of the GET. Use the Get object's capRow or capCol variable to change the screen position of the caption.
When present, the & character specifies that the character immediately following it in the caption is the list box's accelerator key. The accelerator key provides a quick and convenient mechanism for the user to move input focus from one data input control to the list box. The user performs the selection by pressing the Alt key in combination with an accelerator key. The case of an accelerator key is ignored.
MESSAGEcMessage specifies a character string that is displayed on the Get system's status bar line when the GET has input focus. Typically, it describes the anticipated contents or user response of the GET. Refer to the READ command for details pertaining to the Get system's status bar.
WHENlPreExpression specifies an expression that must be satisfied before the cursor can enter the GET during a READ. The expression can optionally be a code block. The Get object is passed as a parameter to the code block.
VALIDlPostExpression specifies an expression that must be satisfied before the cursor can leave the GET during a READ. The expression can optionally be a code block. The Get object is passed as a parameter to the code block.
COLORcColorString defines the color settings for the list box. cColorString is a character expression containing exactly seven color settings if there is no drop-down list box, and eight if there is a drop-down list box.
ListBox Color Attributes
Position Applies To Default Value from
in colorSpec System Color Setting
1 List box items that are not selected Unselected
when the list does not have input focus
2 The selected list box item when the Unselected
List does not have input focus
3 List box items that are not selected Unselected
when the list has input focus
4 The selected list box item when the Enhanced
list has input focus
5 The list box's border Border
6 The list box's caption Standard
7 The list box caption's accelerator key Background
8 The list box's drop-down button Standard
Note: In graphic mode, colorSpec position 8 has no affect and is ignored.
FOCUSfblock specifies a code block that is evaluated each time the list box receives focus. The code block takes no implicit arguments. Use the PushButton:hasFocus instance variable to determine if the push button has focus.
STATEbBlock specifies a code block that is evaluated immediately after the list box object's selection changes. The code block takes no implicit arguments. Use the ListBox:buffer instance variable to determine the current selection.
DROPDOWN indicates that the list box will be a drop-down list box. Drop-down list boxes are displayed differently on the screen than regular list boxes. A regular list box is always displayed regardless of whether it has input focus. A drop-down list box's display behavior is determined by whether it is closed or open. By default, a drop-down list box is closed. In this case, only the caption, the selected item, and the open button are displayed.
When open, the actual list box is displayed in addition to the caption, selected item, and open button.
Drop-down list boxes are useful in situations where screen space is limited.
SCROLLBAR indicates that the list box will be created with a scroll bar whether or not it is needed. Normally a scroll bar is not needed if the data being displayed fits inside the list box.
SENDmsg sends the specified message to the Get object. msg is sent before the GET is displayed. Any message can be sent, including method calls and instance variable assignments. Method calls must include parentheses even if no arguments are passed.
GUISENDguimsg can be used to send a message (such as the display() method) to a GUI object. The GUI objects available in CA-Clipper are check boxes, list boxes, push buttons, and radio button groups. To send a message to a non-GUI object, such as standard GETs and TBrowses, use the SEND clause.
BITMAPcBitmap defines the bitmap that will be used as the down arrow on a drop-down list box. Drive and directory names are not allowed; the file name extension is required. A bitmap file can be stored as a file on disk or in a bitmap library. If stored as a file, the file must reside in the same directory as the application. If stored in a bitmap library, the library must reside in the same directory as the application and it also must have the same name as the application with a .bml extension.
CA-Clipper will search for the file name first and, if it is not found, search in the bitmap library second. If no file is found either on disk or in the library, no bitmap will be displayed.
Examples
■ This example demonstrates how to add a list box to a data
entry screen. It utilizes the position-oriented method of selection:
nColor := 1 //default to the first item.
@ 5, 20, 8, 28 GET nColor LISTBOX { "Red", Green", "Blue" }
■ This example demonstrates a list box that has a caption and a
message. It utilizes the data-oriented method of selection:
cColor := "Red" //default to red.
@ 5, 20, 8, 28 GET cColor LISTBOX { "Red", Green", "Blue" };
CAPTION "&Color" ;
MESSAGE "Select the background color"
■ This example demonstrates a list box that utilizes a two-
dimensional array.
cState := "NY"
@ 5, 20, 10, 30 GET cState LISTBOX { { "Alabama", "AL" }, ;
{ "Alaska", AK" } , ;
{ "Arizona", "AZ" }, ;
{ etc... } } ;
CAPTION "&State" ;
MESSAGE "Select the client's state"
Create a new push button Get object and display it to the screen
Syntax
@ <nRow>, <nCol>
GET <lVar>
PUSHBUTTON
[CAPTION<cCaption>]
[MESSAGE <cMessage>]
[WHEN <lPreExpression>]
[VALID <lPostExpression>]
[COLOR <cColorString>]
[FOCUS <fblock>
[STATE <bBlock>]
[STYLE <cStyle>]
[SEND <msg>]
[GUISEND <guimsg>]
[SIZE X <nSizeX> Y <nSizeY>]
[CAPOFF X <nCapXOff> Y <nCapYOff>]
[BITMAP <cBitmap>]
[BMPOFF X <nBmpXOff> Y <nBmpYOff>]
Arguments
nRow and nCol specify the row and column coordinates for the push button and its caption. Output which extends beyond the visible extent of the display is clipped and does not appear.
GETlVar specifies the name of the variable associated with the GET. lVar may contain a value of any type, but upon return from the READ, will always contain logical false (.F.). The purpose of lVar is to provide a place holder in the GetList for the push button.
CAPTIONcCaption specifies a character string that concisely describes the GET on the screen. caption differs from the SAY argument in two ways. The first is that the caption is displayed each time the GET is shown on the screen. The other difference is that the caption, along with its screen position, is maintained within the Get object. This allows the GET to receive input when the mouse's left button is clicked and its cursor is on the caption. By default, the caption appears within the push button's border. Use the Get object's capRow or capCol variable to change the screen position of the caption.
When present, the & character specifies that the character immediately following it in the caption is the push button's accelerator key. The accelerator key provides a quick and convenient mechanism for the user to move input focus from one data input control to the push button. The case of an accelerator key is ignored.
MESSAGEcMessage specifies a character string that is displayed on the Get system's status bar line when the GET has input focus. Typically, it describes the anticipated contents or user response of the GET. Refer to the READ command for details pertaining to the Get system's status bar.
WHENlPreExpression specifies an expression that must be satisfied before the cursor can enter the GET during a READ. The expression can optionally be a code block. The Get object is passed as a parameter to the code block.
VALIDlPostExpression specifies an expression that must be satisfied before the cursor can leave the GET during a READ. The expression can optionally be a code block. The Get object is passed as a parameter to the code block.
COLORcColorString defines the color settings for the push button. cColorString is a character expression containing exactly four color settings.
PushButton Color Attributes
Position Applies To Default Value from
in colorSpec System Color Setting
1 The push button when it does not have Unselected
input focus
2 The push button when it has input focus Enhanced
and is not pressed
3 The push button when it has input focus Standard
and is pressed
4 The push button caption's accelerator Background
key
Note: The background colors of the PushButton Color Attributes are ignored in graphic mode.
FOCUSfblock specifies a code block that is evaluated each time the push button recieves focus. The code block takes no implicit arguments. Use the PushButton:hasFocus instance variable to determine if the push button has focus.
STATEbBlock specifies a code block that is evaluated each time the push button object's state changes. The code block takes no implicit arguments. Use the PushButton:buffer instance variable to determine if the push button is pressed or released. A value of true (.T.) indicates that it is being pressed; otherwise, a value of false (.F.) indicates that it is being released.
STYLEcStyle specifies a character string that indicates the delimiter characters that are used by the push button's display() method. When specified, the string must contain either zero, two, or eight characters. The default is two characters. The first is the left delimiter. Its default value is the less than () character. The second character is the right delimiter. Its default value is the greater than () character.
When the style string is empty, the button has no delimiters. When the string length is two, the button has left and right delimiters and occupies one row on the screen. The first character is the left delimiter. The second character is the right delimiter. When the string length is eight, the button is contained within a box that occupies three rows on the screen.
Box.ch contains manifest constants for the PushButton:style value.
The default style for the @...GETPUSHBUTTON is "<>".
Note: The Style clause is ignored in graphic mode.
SENDmsg sends the specified message to the Get object. msg is sent before the GET is displayed. Any message can be sent, including method calls and instance variable assignments. Method calls must include parentheses even if no arguments are passed.
GUISENDguimsg can be used to send a message (such as the display() method) to a GUI object. The GUI objects available in CA-Clipper are check boxes, list boxes, push buttons, and radio button groups. To send a message to a non-GUI object, such as standard GETs and TBrowses, use the SEND clause.
SIZE X nSizeX Y nSizeY defines the size of the button to be displayed. The coordinates are in pixels. nSizeX represents the number of pixels in the x direction (horizontally) and nSizeY represents the number of pixels in the y direction (vertically). This argument only affects applications running in graphic mode and is ignored in text mode.
CAPOFF X nCapXOff Y nCapYOff defines the offset where the caption is displayed. The coordinates are in pixels. nCapXOff represents the number of pixels in the x direction (horizontally) from the left edge of the button where the caption will be displayed. nCapYOff represents the number of pixels in the y direction (vertically) from the top edge of the button where the caption will be displayed. If the CAPOFF clause is not supplied, the caption will be centered on the button. This argument only affects applications running in graphic mode and is ignored in text mode.
BITMAPcBitmap defines a bitmap file to be displayed on the button. Drive and directory names are not allowed; the file name extension is required. A bitmap file can be stored as a file on disk or in a bitmap library. If stored as a file, the file must reside in the same directory as the application. If stored in a bitmap library, the library must reside in the same directory as the application and it also must have the same name as the application with a .bml extension.
CA-Clipper will search for the file name first and, if it is not found, search in the bitmap library second. If no file is found either on disk or in the library, no bitmap will be displayed.
BMPOFF X nBmpXOff Y nBmpYOff defines the offset where the bitmap is displayed. The coordinates are in pixels. nCapXOff represents the number of pixels in the x direction (horizontally) from the left edge where the bitmap will be displayed. nCapYOff represents the number of pixels in the y direction (vertically) from the top edge where the bitmap will be displayed. If the BMPOFF clause is not supplied, the bitmap will be placed at the upper-left corner of the button. This argument only affects applications running in graphic mode and is ignored in text mode.
Examples
■ This example demonstrates how to add a push button to a data
entry screen:
@ 5, 20 GET lCancel PUSHBUTTON ;
CAPTION "&Cancel"
STATE { || ReadKill( .T. ) }
nTop, nLeft, nBottom and nRight specify the screen position for the radio button group and its caption. Output which extends beyond the visible extent of the display is clipped and does not appear.
GETnVar|cVar specifies the name of the variable associated with the GET. Its value indicates which radio button (if any) in the group is selected. A numeric value refers to the position in the group of the selected button. A value of 0 indicates no selected button. A character string value refers to the data or text contained within the selected button. A character string that does not refer to any item in the list indicates no selected item.
RADIOGROUPaGroup specifies an array of RadioButto objects.
CAPTIONcCaption specifies a character string that concisely describes the GET on the screen. Caption differs from the SAY argument in two ways. The first is that the caption is displayed each time the GET is shown on the screen. The other difference is that the caption, along with its screen position is maintained within the Get object. This allows the GET to receive input when the mouse's left button is clicked and its cursor is on the caption. By default, the caption appears in the top-left border of the GET. Use the Get object's capRow or capCol variable to change the screen position of the caption.
When present, the & character specifies that the character immediately following it in the caption is the radio group's accelerator key. The accelerator key provides a quick and convenient mechanism for the user to move input focus from one data input control to the radio group. The case of an accelerator key is ignored.
MESSAGEcMessage specifies a character string that is displayed on the Get system's status bar line when the GET has input focus. Typically, it describes the anticipated contents or user response of the GET. Refer to the READ command for details pertaining to the Get system's status bar.
COLORcColorString defines the color settings for the radio button group. cColorString is a character expression containing exactly three color settings.
RadioGroup Color Attributes
Position Applies To Default Value from
in colorSpec System Color Setting
1 The radio group's border Border
2 The radio group's caption Standard
3 The radio group caption's accelerator key Background
FOCUSfblock specifies a code block that is evaluated each time the radio button group receives focus. The code block takes no implicit arguments. Use the RadioGroup:hasFocus instance variable to determine if the radio group has focus.
WHENlPreExpression specifies an expression that must be satisfied before the cursor can enter the GET during a READ. The expression can optionally be a code block. The Get object is passed as a parameter to the code block.
VALIDlPostExpression specifies an expression that must be satisfied before the cursor can leave the GET during a READ. The expression can optionally be a code block. The Get object is passed as a parameter to the code block.
Note: There is no STATE clause for the @...GETRADIOGROUP command. Instead each radio button in the group can have its own sBlock instance variable. See sBlock under RadioButto class for more details.
SENDmsg sends the specified message to the Get object. msg is sent before the GET is displayed. Any message can be sent, including method calls and instance variable assignments. Method calls must include parentheses even if no arguments are passed.
GUISENDguimsg can be used to send a message (such as the display() method) to a GUI object. The GUI objects available in CA-Clipper are check boxes, list boxes, push buttons, and radio button groups. To send a message to a non-GUI object, such as standard GETs and TBrowses, use the SEND clause.
Examples
■ This example demonstrates how to add a radio button group to a
data entry screen. It utilizes a position-oriented method of
selection:
nColor := 1 //default to the first item.
aGroup := Array( 3 )
aGroup[ 1 ] := RadioButto( 6, 22, "&Red" )
aGroup[ 2 ] := RadioButto( 7, 22, "&Green" )
aGroup[ 3 ] := RadioButto( 8, 22, "&Blue" )
@ 5, 20, 9, 40 GET nColor RADIOGROUP aGroup
The nColor variable will return a position, in this case 1, 2, or 3.
■ This example demonstrates a radio button group that utilizes a
data-oriented method of selection:
cColor := "R" //default to red.
aGroup := Array( 3 )
aGroup[ 1 ] := RadioButto( 6, 22, "&Red", "R" )
aGroup[ 2 ] := RadioButto( 7, 22, "&Green", "G" )
aGroup[ 3 ] := RadioButto( 8, 22, "&Blue", "B" )
@ 5, 15, 9, 40 GET cColor RADIOGROUP aGroup
The nColor variable will return data, in this case "R", "G", or "B".
nTop, nLeft, nBottom and nRight specify the screen position for the TBrowse object. Output which extends beyond the visible extent of the display is clipped and does not appear.
GETidVar specifies the name of the variable associated with the GET. Its value is neither queried nor modified by the Get system. The GET is merely a mechanism used for integrating a TBrowse object into the @...GET/READ system.
TBROWSEoTBrowse specifies a previously defined TBrowse object.
MESSAGEcMessage specifies a character string that is displayed on the Get system's status bar line when the GET has input focus. Typically, it describes the anticipated contents or user response of the GET. Refer to the READ command for details pertaining to the Get system's status bar.
WHENlPreExpression specifies an expression that must be satisfied before the cursor can enter the GET during a READ. The expression can optionally be a code block. The Get object is passed as a parameter to the code block.
VALIDlPostExpression specifies an expression that must be satisfied before the cursor can leave the GET during a READ. The expression can optionally be a code block. The Get object is passed as a parameter to the code block.
SENDmsg sends the specified message to the Get object. msg is sent before the GET is displayed. Any message can be sent, including method calls and instance variable assignments. Method calls must include parentheses even if no arguments are passed.
GUISENDguimsg can be used to send a message (such as the display() method) to a GUI object. The GUI objects available in CA-Clipper are check boxes, list boxes, push buttons, and radio button groups. To send a message to a non-GUI object, such as standard GETs and TBrowses, use the SEND clause.
Examples
■ This example demonstrates how to add a TBrowse object to a
data entry screen:
oTB := TBrowseDB( 10, 10, 15, 40 )
oTB:AddColumn(TBColumnNew("Last Name",{||Customer->lName}))
oTB:AddColumn(TBColumnNew("First Name",{||Customer->fName}))
oTB:AddColumn(TBColumnNew("Phone",{||Customer->Phone}))
uDummy := NIL
@ 10, 10, 15, 40 GET uDummy TBROWSE oTB
nRow and nCol are the row and column coordinates of the menu item display. Row values can range from zero to MaxRow(), and column values can range from zero to MaxCol().
PROMPTcMenuItem is the menu item string to display.
MESSAGEcExpression defines the message to display each time the current menu item is highlighted. A code block evaluating to a character expression may optionally be used.
Description
@...PROMPT is the display portion of the CA-Clipper lightbar menu system. Each @...PROMPT command paints a menu item in the current standard color and defines an associated MESSAGE to be displayed on the line specified by SET MESSAGE. The lightbar menu is then invoked with MENU TO. You can specify menu items in any order and configuration of row and column position. MENU TO, however, navigates the current list of menu items in the order they were defined. You can define up to 4096 menu items for each menu.
After each @...PROMPT command, the cursor is located one column position to the right of the last menu item character and Row() and Col() are updated to reflect the new cursor position. This lets you use Row() and Col() to specify consecutive menu item positions relative to the first one painted. See the example below.
Examples
■ This example displays a lightbar menu with the associated
messages displayed on the next line. When the user presses Return,
the position of the item in the list of menu items is assigned to
nChoice:
LOCAL nChoice := 1
SET WRAP ON
SET MESSAGE TO 2
@ 1, 3 PROMPT "File" MESSAGE "Access data files"
@ Row(), Col() + 2 PROMPT "Edit" ;
MESSAGE "Edit current record"
MENU TO nChoice
■ This example shows how to pass the MESSAGE clause a code block
which calls a user-defined function that displays a message in a
different color:
SET COLOR TO gr+/b,r+/n
SET MESSAGE TO 23 // This is necessary.
CLEAR SCREEN
@ 3,4 PROMPT "one " MESSAGE {||UDF("Message One ")}
@ 4,4 PROMPT "two " MESSAGE {||UDF("Message Two ")}
@ 5,4 PROMPT "three" MESSAGE {||UDF("Message Three")}
MENU TO test
FUNCTION UDF(cParm)
cOldColor := SetColor("w+/n")
@ 22,1 SAY cParm // Must be different row than the
// SET MESSAGE TO nRow
SetColor(cOldColor)
RETURN "" // Character string must be returned
Display data at a specified screen or printer row and column
Syntax
@ <nRow>, <nCol>
SAY <exp> [PICTURE <cSayPicture>]
[COLOR <cColorString>]
Arguments
nRow and nCol are the row and column coordinates of the display. Row values can range from zero to a maximum of MaxRow(), if the current DEVICE is the SCREEN, or 32,766, if the current DEVICE is the PRINTER. Also, column values can range from zero to a maximum of MaxCol() or 32,766 if the current DEVICE is the PRINTER.
SAYexp displays the result of a character, date, logical, or numeric expression to the current DEVICE.
PICTUREcSayPicture defines the formatting control for the display of exp. CA-Clipper provides two mechanisms, functions and templates, to control formatting. Functions apply to an entire SAY, while templates format characters position by position.
COLORcColorString defines the display color of exp. If not specified, exp displays in the standard color as defined by SetColor(). cColorString is a character expression containing the standard color setting. If you specify a literal color setting, it must be enclosed in quote marks.
On a combined @...SAY...GET command, two COLOR clauses are required to specify colors for both the SAY and the GET: one for the SAY and one for the GET.
Description
@...SAY is a full-screen command that outputs the results of exp to either the screen or the printer at the specified row and column coordinates. It can optionally format output using the PICTURE clause. @...SAY creates data entry screens or reports that can be sent to the screen or printer.
When an @...SAY command executes , the output from exp is sent to the current device defined with SET DEVICE. The current DEVICE can be the SCREEN or PRINTER. Unlike console commands, @...SAY output to the printer is not echoed to the screen and SET CONSOLE has no effect on @...SAY output to the screen.
If the current DEVICE is the SCREEN (the system default), @...SAY displays output to the screen leaving the cursor one column position to the right of the last character displayed. Row() and Col() are then updated with this position. Output that displays off the screen, as defined by MaxRow() and MaxCol(), is clipped and the cursor is positioned beyond the visible screen. All @...SAY output displays are in standard color. Refer to the SetColor() reference in this chapter for more information on color.
If the current DEVICE is set to PRINTER, the display is directed to the printer at the specified nRow and nCol position. If the current MARGIN value is greater than zero, it is added to nCol first. The printhead is then advanced one column position to the right of the last character output and PRow() and PCol() are updated. @...SAY commands to the printer behave differently from those to the screen if output is addressed to a printer row or column position less than the current PRow() and PCol() values:
■ If nRow is less than PRow(), an automatic EJECT (Chr(12)) is
sent to the printer followed by the number of linefeed characters (Chr(10)) required to position the printhead on nRow on the following page
■ If nCol including the SET MARGIN value is less than PCol(),
a carriage return character (Chr(13)) and the number of spaces required to position exp at nCol are sent to the printer
To override this behavior and send control codes to the printer, or for any other reason, you can use SetPRC() to reset PRow() and PCol() to new values. See the SetPRC() function reference for more information.
If the current DEVICE is the PRINTER, redirect output from @...SAY commands to a file using the SET PRINTER TOxcFile command.
@...SAY command output can be formatted using the PICTURE clause with a cSayPicture. This performs the same action as the Transform() function. A cSayPicture may consist of a function and/or a template. A PICTURE function imposes a rule on the entire @...SAY output. A PICTURE template defines the length of the @...SAY output and the formatting rule for each position within the output.
■ Function string: A PICTURE function string specifies
formatting rules which apply to the SAY's entire display value, rather than to particular character positions within it. The function string consists of the @ character, followed by one or more additional characters, each of which has a particular meaning (see table below). The function string must not contain spaces. A function string may be specified alone or with a template string. If both are present, the function string must precede the template string, and the two must be separated by a single space.
■ Template string: A PICTURE template string specifies
formatting rules on a character-by-character basis. The template string consists of a series of characters, some of which have special meanings (see table below). Each position in the template string corresponds to a position in the displayed SAY value. Characters in the template string that do not have assigned meanings are copied verbatim into the displayed SAY value. If you use the @R picture function, characters without special PICTURE template string meaning are inserted between characters of the display value; otherwise, they overwrite the corresponding characters of the display value. You may specify a template string alone or with a function string. If both are present, the function string must precede the template string, and the two must be separated by a single space.
$ Displays a dollar sign in place of a leading space in a
number
* Displays an asterisk in place of a leading space in a
number
. Specifies a decimal point position
, Specifies a comma position
Examples
■ This example uses an @...SAY with a PICTURE clause to display
formatted output:
nNetIncome = 7125.50
nNetLoss = -125.50
cPhone = "2134567890"
cName = "Kate Mystic"
//
@ 1, 1 SAY nNetIncome PICTURE "@E 9,999.99"
// Result: 7.125,50
@ 2, 1 SAY nNetLoss PICTURE "@)"
// Result: (125.50)
@ 3, 1 SAY cPhone PICTURE "@R (999)999-9999"
// Result: (213)456-7890
@ 4, 1 SAY cName PICTURE "@!"
// Result: KATE MYSTIC
■ This example is a small label printing program that uses SET
DEVICE to direct output to the printer and SetPRC() to suppress
automatic EJECTs:
USE Salesman INDEX Salesman NEW
SET DEVICE TO PRINTER
DO WHILE !Eof() // Print all records
@ 2, 5 SAY RTrim(FirstName) + ", " + LastName
@ 3, 5 SAY Street
@ 4, 5 SAY RTrim(City) + ", " + State + " " + ;
PostalCode
@ 6, 0 SAY Space(1) // Move to label bottom
SetPRC(0, 0) // Suppress page eject
SKIP // Next record
ENDDO
SET DEVICE TO SCREEN
CLOSE Salesman
@ <nTop>, <nLeft>
TO <nBottom>, <nRight> [DOUBLE] [COLOR <cColorString>]
Arguments
nTop, nLeft, nBottom, and nRight define the coordinates of the box. @...TO draws the box using row values from zero to MaxRow() and column values from zero to MaxCol(). nBottom and nRight can be larger than the screen size, but output is clipped at MaxRow() and MaxCol().
DOUBLE draws the box with a double line. If not specified, the box is drawn with a single line.
COLORcColorString defines the display color of the drawn box. If not specified, the box is drawn using the standard color setting of the current system color as defined by SetColor(). Note that cColorString is a character expression containing the standard color setting. If you specify a literal color setting, enclose it within quote marks.
Description
@...TO draws a single- or double-line box on the screen. If nTop and nBottom are the same, a horizontal line is drawn. If nLeft and nRight are the same, a vertical line is drawn.
After @...TO finishes drawing, the cursor is located in the upper-left corner of the boxed region at nTop + 1 and nLeft + 1. Row() and Col() are also updated to reflect the new cursor position.
@...TO is like @...BOX except that @...BOX lets you define the characters of the box and supports a fill character. @...TO, however, is recommended for portability since it does not require the specification of hardware-dependent graphics characters.
Examples
■ This example erases a region of the screen, then draws a box
of the same size:
@ 10, 10 CLEAR TO 20, 40
@ 10, 10 TO 20, 40 DOUBLE COLOR "BG+/B"
The $ operator is a binary relational operator that performs a case- sensitive substring search and returns true (.T.) if cString1 is found within cString2.
Examples
■ This example illustrates the case-sensitivity of the substring
operator ($):
? "A" $ "ABC" // Result: .T.
? "a" $ "ABC" // Result: .F.
The macro operator in CA-Clipper is a special operator that allows runtime compilation of expressions and text substitution within strings. Whenever the macro operator (&) is encountered, the operand is submitted to a special runtime compiler (the macro compiler) that compiles expressions, but not statements or commands.
Text Substitution
Whenever a reference to a private or public macro variable, embedded in a character string, is encountered, the variable reference is replaced by the content of the macro variable. For example,
cMacro := "there" ? "Hello &cMacro" // Result: Hello there
If you specify a macro expression (e.g., &(cMacro1 + cMacro2)), and the macro variable is a local, static, field variable, or an array element, it is treated as literal text and not expanded.
Macro operator:nesting Compile and Run
When a macro variable or expression specified within an expression is encountered, it is treated like an expression, with the macro symbol behaving as the compile and run operator. If the macro is specified as a macro variable,
the macro compiler compiles, then executes the content of the macro variable. The compiled code is then discarded.
If you specify an expression enclosed in parentheses and prefaced by the macro operator (&),
? &(IndexKey(0))
the expression is evaluated and the resulting character string is compiled and run as a macro variable.
Using the macro operator, you can compile a character string containing a code block definition:
bBlock := &("{ |exp| QOut(exp) }")
The run portion of the operation returns the code block as a value. You may then use the code block by invoking it with the Eval() function. This is especially significant in activations that involve extensive looping through user-defined conditions (operations that in earlier versions of CA-Clipper required macro expansion). In those versions, the macro expression was compiled and run for each iteration of the loop. With the combination of a macro expansion and a code block Eval(), the compilation is performed once at compile time, and the Eval() merely executes the code block each time through the loop:
■ Command keywords: You cannot use the macro operator (&) to
substitute or compile command keywords. However, you can redefine command keywords by modifying the command definition in std.ch, overriding an existing command definition with a new definition using the #command directive, or redefining a command keyword using the #translate directive. In any case, you may redefine a command keyword only at compile time, not at runtime.
■ Command arguments: In prior versions of CA-Clipper as well as
in other dialects, you could use macro variables as the arguments of commands requiring literal text values. These included all file command arguments and SET commands with toggle arguments. In these instances, you can now use an extended expression enclosed in parentheses in place of the literal argument. For example,
xcDatabase = "Invoices" USE &xcDatabase.
can be replaced with:
xcDatabase = "Invoices" USE (xcDatabase)
It is important to use extended expressions if you are using local and static variables. Generally, commands are preprocessed into function calls with command arguments translated into function arguments as valid CA-Clipper values. File names in file commands, for instance, are stringified using the smart stringify result marker and passed as arguments to the functions that actually perform the desired actions. If you specify a literal or macro value as the command argument, it is stringified. If, however, the argument is an extended expression, it is written to the result text exactly as specified. This example,
#command RENAMExcOldTOxcNew; =>;
FRename( (xcOld), (xcNew) )
// RENAME &xcOld TO &xcNew RENAME (xcOld) TO (xcNew)
when preprocessed. When the macro variables are stringified, the macro variable names are hidden in the string and not compiled. Later, at runtime, they are substituted into the string and passed as arguments to the FRename() function. This precludes local and static macro variables since the names of the variables are not present at runtime to be substituted. Public and private variables, however, behave as expected.
■ Lists as arguments of commands: The macro operator (&) will
not fully substitute or compile a list as an argument of most commands. In particular, these are commands where an argument list is preprocessed into an array or a code block. Instances of this are arguments of the FIELDS clause and SET INDEX. An exception is the SET COLOR command which preprocesses the list of colors into a single character string and passes it to the SetColor() function.
In any case, list arguments should always be specified as extended expressions with each list argument specified:
LOCAL xcIndex := { "Ntx1", "Ntx2" } SET INDEX TO (xcIndex[1]), (xcIndex[2])
■ Arrays: You can use the macro operator (&) with arrays and
array elements. However, because of the increased power of CA-Clipper arrays, you may find less need to use the macro operator (&) to make variable references to arrays. You can now assign array references to variables, return array references from user-defined functions, and nest array references within other arrays. You may also create arrays by specifying literal arrays or using the Array() function.
You can, therefore, make references to arrays and array elements using both macro variables and macro expressions with the restriction that you cannot make the subscript references in a PRIVATE or PUBLIC statement. Also, you cannot specify the macro operator (&) in a declaration statement, such as a LOCAL or STATIC statement. Attempting this will generate a fatal compiler error.
This example references array elements using macro variables:
&cNameElement. := 100 // Assigns 100 to element 1 &cName.[3] := "abc" // Assigns "abc" to element 3
You can successfully apply a macro operator (&) to an array element if the reference is made using a macro expression. A macro variable reference, however, will generate a runtime error. For example, the following lists the values of all fields of the current record:
USE Customer NEW aStruc := dbStruct() // FOR nField := 1 TO Len(aStruc)
? &(aStruc[nField, 1])
NEXT
■ Code blocks: You can apply the macro operator (&) to a macro
variable or expression in a code block in most cases. There is a restriction when the macro variable or macro expression contains a declared variable. A runtime error occurs if you specify a complex expression (an expression that contains an operator and one or more operands) that includes the macro operator (&) within a code block.
This has important implications for the use of local and static variables in the conditional clauses of commands, since these clauses are blockified as they are written to the result text during preprocessing. This applies to all FOR and WHILE clauses, the SET FILTER command, and the SET RELATION linking expression. The general workaround is to gather the entire expression into a single macro variable then apply the macro operator (&) to the variable.
■ Macro conditions: When using the macro operator (&) to specify
conditional clauses of database commands such as FOR or WHILE clauses, there are some restrictions based on the expression's complexity and size:
- The maximum string size the macro compiler can process is 254
characters.
- There is a limit to the complexity of conditions (the more
complex, the fewer the number of conditions you can specify).
■ Procedures and functions: You can reference procedure and
function calls using macro variables and expressions. With DO, the macro variable reference to the procedure can be all or part of the procedure name. With a call to a function (built-in or user- defined), the macro variable reference must include the function name and all of its arguments.
In CA-Clipper, because of the added facility code blocks, all invocations of procedures and functions using the macro operator should be converted to the evaluation of code blocks. This code fragment
The advantage of a code block over a macro evaluation is that the result of the compilation of a string containing a code block can be saved and, therefore, need only be compiled once. Macro evaluations compile each time they are referenced.
■ References into overlays: You must declare procedures and
user-defined functions that are used in macro expressions and variables but not referenced elsewhere as EXTERNAL, or the linker will not include them into the executable (.EXE) file.
■ TEXT...ENDTEXT: Macro variables referenced within a
TEXT...ENDTEXT construct are expanded. Note that a field cannot be expanded, so you must first assign the field value to a memory variable then reference the memory variable as a macro variable within the TEXT...ENDTEXT. For example:
USE Customer NEW myVar := Customer->CustName TEXT This is text with a macro &myVar ENDTEXT
■ Nested macros: The processing of macro variables and
expressions in CA-Clipper permits nested macro definitions. For example, after assigning a macro variable to another macro variable, the original macro variable can be expanded resulting in the expansion of the second macro variable and evaluation of its contents:
matchPattern is the pattern the input text should match.
resultPattern is the text produced if a portion of input text matches the matchPattern.
The => symbol between matchPattern and resultPattern is, along with #command or #translate, a literal part of the syntax that must be specified in a #command or #translate directive. The symbol consists of an equal sign followed by a greater than symbol with no intervening spaces. Do not confuse the symbol with the >= or the <= comparison operators in the CA-Clipper language.
Description
#command and #translate are translation directives that define commands and pseudofunctions. Each directive specifies a translation rule. The rule consists of two portions: a match pattern and a result pattern. The match pattern matches a command specified in the program (.prg) file and saves portions of the command text (usually command arguments) for the result pattern to use. The result pattern then defines what will be written to the result text and how it will be written using the saved portions of the matching input text.
#command and #translate are similar, but differ in the circumstance under which their match patterns match input text. A #command directive matches only if the input text is a complete statement, while #translate matches input text that is not a complete statement. #command defines a complete command and #translate defines clauses and pseudofunctions that may not form a complete statement. In general, use #command for most definitions and #translate for special cases.
#command and #translate are similar to but more powerful than the #define directive. #define, generally, defines identifiers that control conditional compilation and manifest constants for commonly used constant values such as Inkey() codes. Refer to any of the header files in the \CLIP53\INCLUDE directory for examples of manifest constants defined using #define.
#command and #translate directives have the same scope as the #define directive. The definition is valid only for the current program (.prg) file unless defined in std.ch or the header specified with the /U option on the compiler command line. If defined elsewhere, the definition is valid from the line where it is specified to the end of the program file. Unlike #define, a #translate or #command definition cannot be explicitly undefined. The #undef directive has no effect on a #command or #translate definition.
As the preprocessor encounters each source line preprocessor, it scans for definitions in the following order of precedence: #define, #translate, and #command. When there is a match, the substitution is made to the result text and the entire line is reprocessed until there are no matches for any of the three types of definitions. #command and #translate rules are processed in stack-order (i.e., last in-first out, with the most recently specified rule processed first).
In general, a command definition provides a way to specify an English language statement that is, in fact, a complicated expression or function call, thereby improving the readability of source code. You can use a command in place of an expression or function call to impose order of keywords, required arguments, combinations of arguments that must be specified together, and mutually exclusive arguments at compile time rather than at runtime. This can be important since procedures and user-defined functions can now be called with any number of arguments, forcing any argument checking to occur at runtime. With command definitions, the preprocessor handles some of this.
All commands in CA-Clipper are defined using the #command directive and supplied in the standard header file, std.ch, located in the \CLIP53\INCLUDE directory. The syntax rules of #command and #translate facilitate the processing of all CA-Clipper and dBASE-style commands into expressions and function calls. This provides CA-Clipper compatibility, as well as avenues of compatibility with other dialects.
When defining a command, there are several prerequisites to properly specifying the command definition. Many preprocessor commands require more than one #command directive because mutually exclusive clauses contain a keyword or argument. For example, the @...GET command has mutually exclusive VALID and RANGE clauses and is defined with a different #command rule to implement each clause.
This also occurs when a result pattern contains different expressions, functions, or parameter structures for different clauses specified for the same command (e.g., the @...SAY command). In std.ch, there is a #command rule for @...SAY specified with the PICTURE clause and another for @...SAY specified without the PICTURE clause. Each formulation of the command is translated into a different expression. Because directives are processed in stack order, when defining more than one rule for a command, place the most general case first, followed by the more specific ones. This ensures that the proper rule will match the command specified in the program (.prg) file.
For more information and a general discussion of commands, refer to the "Basic Concepts" chapter in the Programming and Utilities Guide.
Match Pattern
The matchPattern portion of a translation directive is the pattern the input text must match. A match pattern is made from one or more of the following components, which the preprocessor tries to match against input text in a specific way:
■ Literal values are actual characters that appear in the match
pattern. These characters must appear in the input text, exactly as specified to activate the translation directive.
■ Words are keywords and valid identifiers that are compared
according to the dBASE convention (case-insensitive, first four letters mandatory, etc.). The match pattern must start with a Word.
#xcommand and #xtranslate can recognize keywords of more than four significant letters.
■ Match markers are label and optional symbols delimited by
angle brackets (<>) that provide a substitute (idMarker) to be used in the resultPattern and identify the clause for which it is a substitute. Marker names are identifiers and must, therefore, follow the CA-Clipper identifier naming conventions. In short, the name must start with an alphabetic or underscore character, which may be followed by alphanumeric or underscore characters.
This table describes all match marker forms:
Match Markers
Match Marker Name
<idMarker> Regular match marker
<idMarker,...> List match marker
<idMarker:word list> Restricted match marker
<*idMarker*> Wild match marker
<(idMarker)> Extended Expression match marker
- Regular match marker: Matches the next legal expression in the
input text. The regular match marker, a simple label, is the most general and, therefore, the most likely match marker to use for a command argument. Because of its generality, it is used with the regular result marker, all of the stringify result markers, and the blockify result marker.
- List match marker: Matches a comma-separated list of legal
expressions. If no input text matches the match marker, the specified marker name contains nothing. You must take care in making list specifications because extra commas will cause unpredictable and unexpected results.
The list match marker defines command clauses that have lists as arguments. Typically these are FIELDS clauses or expression lists used by database commands. When there is a match for a list match marker, the list is usually written to the result text using either the normal or smart stringify result marker. Often, lists are written as literal arrays by enclosing the result marker in curly ({ }) braces.
- Restricted match marker: Matches input text to one of the
words in a comma-separated list. If the input text does not match at least one of the words, the match fails and the marker name contains nothing.
A restricted match marker is generally used with the logify result marker to write a logical value into the result text. If there is a match for the restricted match marker, the corresponding logify result marker writes true (.T.) to the result text; otherwise, it writes false (.F.). This is particularly useful when defining optional clauses that consist of a command keyword with no accompanying argument. std.ch implements the REST clause of database commands using this form.
- Wild match marker: Matches any input text from the current
position to the end of a statement. Wild match markers generally match input that may not be a legal expression, such as #command NOTE *x* in std.ch, gather the input text to the end of the statement, and write it to the result text using one of the stringify result markers.
- Extended expression match marker: Matches a regular or
extended expression, including a file name or path specification. It is used with the smart stringify result marker to ensure that extended expressions will not get stringified, while normal, unquoted string file specifications will.
■ Optional match clauses are portions of the match pattern
enclosed in square brackets ([ ]). They specify a portion of the match pattern that may be absent from the input text. An optional clause may contain any of the components allowed within a matchPattern, including other optional clauses.
Optional match clauses may appear anywhere and in any order in the match pattern and still match input text. Each match clause may appear only once in the input text. There are two types of optional match clauses: one is a keyword followed by match marker, and the other is a keyword by itself. These two types of optional match clauses can match all of the traditional command clauses typical of the CA-Clipper command set.
Optional match clauses are defined with a regular or list match marker to match input text if the clause consists of an argument or a keyword followed by an argument (see the INDEX clause of the USE command in std.ch). If the optional match clause consists of a keyword by itself, it is matched with a restricted match marker (see the EXCLUSIVE or SHARED clause of the USE command in std.ch).
In any match pattern, you may not specify adjacent optional match clauses consisting solely of match markers, without generating a compiler error. You may repeat an optional clause any number of times in the input text, as long as it is not adjacent to any other optional clause. To write a repeated match clause to the result text, use repeating result clauses in the resultPattern definition.
Result Pattern
The resultPattern portion of a translation directive is the text the preprocessor will produce if a piece of input text matches the matchPattern. resultPattern is made from one or more of the following components:
■ Literal tokens are actual characters that are written directly
to the result text.
■ Words are CA-Clipper keywords and identifiers that are written
directly to the result text.
■ Result markers: refer directly to a match marker name. Input
text matched by the match marker is written to the result text via the result marker.
This table lists the Result marker forms:
Result Markers
Result Marker Name
<idMarker> Regular result marker
#<idMarker> Dumb stringify result marker
<"idMarker"> Normal stringify result marker
<(idMarker)> Smart stringify result marker
<{idMarker}> Blockify result marker
<.idMarker.> Logify result marker
- Regular result marker: Writes the matched input text to the
result text, or nothing if no input text is matched. Use this, the most general result marker, unless you have special requirements. You can use it with any of the match markers, but it almost always is used with the regular match marker.
- Dumb stringify result marker: Stringifies the matched input
text and writes it to the result text. If no input text is matched, it writes a null string (""). If the matched input text is a list matched by a list match marker, this result marker stringifies the entire list and writes it to the result text.
This result marker writes output to result text where a string is always required. This is generally the case for commands where a command or clause argument is specified as a literal value but the result text must always be written as a string even if the argument is not specified.
- Normal stringify result marker: Stringifies the matched input
text and writes it to the result text. If no input text is matched, it writes nothing to the result text. If the matched input text is a list matched by a list match marker, this result marker stringifies each element in the list and writes it to the result text.
The normal stringify result marker is most often used with the blockify result marker to compile an expression while saving a text image of the expression (See the SET FILTER condition and the INDEX key expression in std.ch).
- Smart stringify result marker: Stringifies matched input text
only if source text is enclosed in parentheses. If no input text matched, it writes nothing to the result text. If the matched input text is a list matched by a list match marker, this result marker stringifies each element in the list (using the same stringify rule) and writes it to the result text.
The smart stringify result marker is designed specifically to support extended expressions for commands other than SETs with xlToggle arguments. Extended expressions are command syntax elements that can be specified as literal text or as an expression if enclosed in parentheses. The xcDatabase argument of the USE command is a typical example. For instance, if the matched input for the xcDatabase argument is the word Customer, it is written to the result text as the string "Customer," but the expression (cPath + cDatafile) would be written to the result text unchanged (i.e., without quotes).
- Blockify result marker: Writes matched input text as a code
block without any arguments to the result text. For example, the input text x + 3 would be written to the result text as {|| x + 3}. If no input text is matched, it writes nothing to the result text. If the matched input text is a list matched by a list match marker, this result marker blockifies each element in the list.
The blockify result marker used with the regular and list match markers matches various kinds of expressions and writes them as code blocks to the result text. Remember that a code block is a piece of compiled code to execute sometime later. This is important when defining commands that evaluate expressions more than once per invocation. When defining a command, you can use code blocks to pass an expression to a function and procedure as data rather than as the result of an evaluation. This allows the target routine to evaluate the expression whenever necessary.
In std.ch, the blockify result marker defines database commands where an expression is evaluated for each record. Commonly, these are field or expression lists, FOR and WHILE conditions, or key expressions for commands that perform actions based on key values.
- Logify result marker: Writes true (.T.) to the result text if
any input text is matched; otherwise, it writes false (.F.) to the result text. This result marker does not write the input text itself to the result text.
The logify result marker is generally used with the restricted match marker to write true (.T.) to the result text if an optional clause is specified with no argument; otherwise, it writes false (.F.). In std.ch, this formulation defines the EXCLUSIVE and SHARED clauses of the USE command.
■ Repeating result clauses are portions of the resultPattern
enclosed by square brackets ([ ]). The text within a repeating clause is written to the result text as many times as it has input text for any or all result markers within the clause. If there is no matching input text, the repeating clause is not written to the result text. Repeating clauses, however, cannot be nested. If you need to nest repeating clauses, you probably need an additional #command rule for the current command.
Repeating clauses are the result pattern part of the #command facility that create optional clauses which have arguments. You can match input text with any match marker other than the restricted match marker and write to the result text with any of the corresponding result markers. Typical examples of this facility are the definitions for the STORE and REPLACE commands in std.ch.
Notes
■ Less than operator: If you specify the less than operator (`)
in the resultPattern expression, you must precede it with the escape character ().
■ Multistatement lines: You can specify more than one statement
as a part of the result pattern by separating each statement with a semicolon. If you specify adjacent statements on two separate lines, the first statement must be followed by two semicolons.
Examples
These examples encompass many of the basic techniques you can use when
defining commands with the #command and #translate directives. In
general, these examples are based on standard commands defined in
Std.ch. Note, however, the functions specified in the example result
patterns are not the actual functions found in std.ch, but fictitious
functions specified for illustration only.
■ This example defines the @...BOX command using regular match
markers with regular result markers:
#command @ <top>, <left>, <bottom>, <right> BOX ;
<boxstring>;
=>;
CmdBox( <top>, <left>, <bottom>, ;
<right>,<boxstring> )
■ This example uses a list match marker with a regular result
marker to define the ? command:
#command ? [<list,...>] => QOut(<list>)
■ This example uses a restricted match marker with a logify
result marker to implement an optional clause for a command
definition. In this example, if the ADDITIVE clause is specified,
the logify result marker writes true (.T.) to the result text;
otherwise, it writes false (.F.):
#command RESTORE FROM <file> [<add: ADDITIVE>];
=>;
CmdRestore( <(file)>, <.add.> )
■ This example uses a list match marker with a smart stringify
result marker to write to the result text the list of fields
specified as the argument of a FIELDS clause. In this example, the
field list is written as an array with each field name as an element
of the array:
#command COPY TO <file> [FIELDS <fields,...>];
=>;
CmdCopyAll( <(file)>, { <(fields)> } )
■ These examples use the wild match marker to define a command
that writes nothing to the result text. Do this when attempting to
compile unmodified code developed in another dialect:
#command SET ECHO <*text*> =>
#command SET TALK <*text*> =>
■ These examples use wild match markers with dumb stringify
result markers to match command arguments specified as literals, then
write them to the result text as strings in all cases:
#command SET PATH TO <*path*> => ;
Set( _SET_PATH, #<path> )
#command SET COLOR TO <*spec*> => SetColor( #<spec> )
■ These examples use a normal result marker with the blockify
result marker to both compile an expression and save the text version
of it for later use:
#command SET FILTER TO <xpr>;
=>;
CmdSetFilter( <{xpr}>, <"xpr"> )
#command INDEX ON <key> TO <file>;
=>;
CmdCreateIndex( <(file)>, <"key">, <{key}> )
■ This example demonstrates how the smart stringify result
marker implements a portion of the USE command for those arguments
that can be specified as extended expressions:
#command USE <db> [ALIAS <a>];
=>;
CmdOpenDbf( <(db)>, <(a)> )
■ This example illustrates the importance of the blockify result
marker for defining a database command. Here, the FOR and WHILE
conditions matched in the input text are written to the result text
as code blocks:
#command COUNT [TO <var>];
[FOR <for>] [WHILE <while>];
[NEXT <next>] [RECORD <rec>] [<rest:REST>] [ALL];
=>;
<var> := 0,;
dbEval( {|| <var>++}, <{for}>, <{while}>,;
<next>, <rec>, <.rest.> )
■ In this example the USE command again demonstrates the types
of optional clauses with keywords in the match pattern. one clause
is a keyword followed by a command argument, and the second is solely
a keyword:
#command USE <db> [<new: NEW>] [ALIAS <a>] ;
[INDEX <index,...>][<ex: EXCLUSIVE>] ;
[<sh: SHARED>] [<ro: READONLY>];
=>;
CmdOpenDbf(<(db)>, <(a)>, <.new.>,;
IF(<.sh.> .OR. <.ex.>, !<.ex.>, NIL),;
<.ro.>, {<(index)>})
■ This example uses the STORE command definition to illustrate
the relationship between an optional match clause and a repeating
result clause:
#command STORE <value> TO <var1> [, <varN> ];
=>;
<var1> := [ <varN> := ] <value>
■ This example uses #translate to define a pseudofunction:
#translate AllTrim(<cString>) => LTrim(RTrim(<cString>))
idConstant is the name of an identifier to define.
resultText is the optional replacement text to substitute whenever a valid idConstant is encountered.
idFunction is a pseudofunction definition with an optional argument list (arg list). If you include arg list, it is delimited by parentheses (()) immediately following idFunction.
exp is the replacement expression to substitute when the pseudofunction is encountered. Enclose this expression in parentheses to guarantee precedence of evaluation when the pseudofunction is expanded.
Note: #define identifiers are case-sensitive, where #command and #translate identifiers are not.
Description
The #define directive defines an identifier and, optionally, associates a text replacement string. If specified, replacement text operates much like the search and replace operation of a text editor. As each source line from a program file is processed by the preprocessor, the line is scanned for identifiers. If a currently defined identifier is encountered, the replacement text is substituted in its place.
Identifiers specified with #define follow most of the identifier naming rules in CA-Clipper . Defined identifiers can contain any combination of alphabetic and numeric characters, including underscores. Defined identifiers, however, differ from other identifiers by being case- sensitive. As a convention, defined identifiers are specified in uppercase to distinguish them from other identifiers used within a program. Additionally, identifiers are specified with a one or two letter prefix to group similar identifiers together and guarantee uniqueness. Refer to one of the supplied header files in the \CLIP53\INCLUDE directory for examples.
When specified, each definition must occur on a line by itself. Unlike statements, more than one directive cannot be specified on the same source line. You may continue a definition on a subsequent line by employing a semicolon (;). Each #define directive is specified followed by one or more white space characters (spaces or tabs), a unique identifier, and optional replacement text. Definitions can be nested, allowing one identifier to define another.
A defined identifier has lexical scope like a filewide static variable. It is only valid in the program (.prg) file in which it is defined unless defined in std.ch or the header file specified on the compiler command line with the /U option. Unlike a filewide static variable, a defined identifier is visible from the point where it is defined in the program file until it is either undefined, redefined, or the end of the program file is reached.
You can redefine or undefine existing identifiers. To redefine an identifier, specify a new #define directive with the identifier and the new replacement text as its arguments. The current definition is then overwritten with the new definition, and a compiler warning is issued in case the redefinition is inadvertent. To undefine an identifier, specify an #undef directive with the identifier as its argument. #define directives have three basic purposes:
■ To define a control identifier for #ifdef and #ifndef
■ To define a manifest constant—an identifier defined to
represent a constant value
■ To define a compiler pseudofunction
The following discussion expands these three purposes of the #define directive in your program.
Preprocessor Identifiers
The most basic #define directive defines an identifier with no replacement text. You can use this type of identifier when you need to test for the existence of an identifier with either the #ifdef or #ifndef directives. This is useful to either exclude or include code for conditional compilation. This type of identifier can also be defined using the /D compiler option from the compiler command line. See the examples below.
Manifest Constants
The second form of the #define directive assigns a name to a constant value. This form of identifier is referred to as a manifest constant. For example, you can define a manifest constant for the Inkey() code associated with a key press:
Whenever the preprocessor encounters a manifest constant while scanning a source line, it replaces it with the specified replacement text.
Although you can accomplish this by defining a variable, there are several advantages to using a manifest constant: the compiler generates faster and more compact code for constants than for variables; and variables have memory overhead where manifest constants have no runtime overhead, thus saving memory and increasing execution speed. Furthermore, using a variable to represent a constant value is conceptually inconsistent. A variable by nature changes and a constant does not.
Use a manifest constant instead of a constant for several reasons. First, it increases readability. In the example above, the manifest constant indicates more clearly the key being represented than does the Inkey() code itself. Second, manifest constants localize the definition of constant values, thereby making changes easier to make, and increasing reliability. Third, and a side effect of the second reason, is that manifest constants isolate implementation or environment specifics when they are represented by constant values.
To further isolate the effects of change, manifest constants and other identifiers can be grouped together into header files allowing you to share identifiers between program (.prg) files, applications, and groups of programmers. Using this methodology, definitions can be standardized for use throughout a development organization. Merge header files into the current program file by using the #include directive.
For examples of header files, refer to the supplied header files in the \CLIP53\INCLUDE directory.
Compiler Pseudo-functions
In addition to defining constants as values, the #define directive can also define pseudofunctions that are resolved at compile time. A pseudofunction definition is an identifier immediately followed by an argument list, delimited by parentheses, and the replacement expression. For example:
Pseudofunctions differ from manifest constants by supporting arguments. Whenever the preprocessor scans a source line and encounters a function call that matches the pseudofunction definition, it substitutes the function call with the replacement expression. The arguments of the function call are transported into the replacement expression by the names specified in the argument list of the identifier definition. When the replacement expression is substituted for the pseudofunction, names in the replacement expression are replaced with argument text. For example, the following invocations,
? AREA(10, 12) SETVAR(nValue, 10) ? Max(10, 9)
are replaced by :
? (10 * 12) nValue := 10 ? (IF(10 > 9, 10, 9)
It is important when defining pseudofunctions, that you enclose the result expression in parentheses to enforce the proper order of evaluation. This is particularly important for numeric expressions. In pseudofunctions, you must specify all arguments. If the arguments are not specified, the function call is not expanded as a pseudofunction and exits the preprocessor to the compiler as encountered.
Pseudofunctions do not entail the overhead of a function call and are, therefore, generally faster. They also use less memory. Pseudofunctions, however, are more difficult to debug within the debugger, have a scope different from declared functions and procedures, do not allow skipped arguments, and are case-sensitive.
You can avoid some of these deficiencies by defining a pseudofunction using the #translate directive. #translate pseudofunctions are not case- sensitive, allow optional arguments, and obey the dBASE four-letter rule. See the #translate directive reference in this chapter for more information.
Examples
■ In this example a manifest constant conditionally controls the
compilation of debugging code:
#define DEBUG
.
. <statements>
.
#ifdef DEBUG
Assert(FILE("System.dbf"))
#endif
■ This example defines a manifest constant and substitutes it
for an Inkey() value:
#define K_ESC 27
.
. <statements>
.
IF Inkey() != K_ESC
DoIt()
ELSE
StopIt()
ENDIF
■ This example defines pseudofunctions for the standard
CA-Clipper functions, Max() and AllTrim():
#define Max(arg1, arg2) (IF(arg1 > arg2, ;
arg1, arg2))
#define AllTrim(cString) (RTrim(LTrim(cString)))
.
. <statements>
.
? Max(1, 2)
? AllTrim(" Hello ")
messageText is the text of the message to be displayed. messageText is a literal character string—do not enclose the message in quotations unless you want them to appear as part of the display.
Description
#error causes the compiler to generate error number C2074. If the messageText parameter is specified, an error message is displayed.
Examples
■ This example displays an error message based on whether or not
a NETWORK identifier was defined:
#ifdef NETWORK
#error Network version not implemented.
#endif
identifier is the name of a definition whose existence is being verified.
Description
#ifdef...#endif lets you perform a conditional compilation. It does this by identifying a section of source code to be compiled if the specified identifier is defined. The identifier can be defined using either the #define directive or the /D compiler option which lets you define an identifier or manifest constant from the compiler command line.
The #else directive specifies the code to compile if identifier is undefined. The #endif terminates the conditional compilation block.
Conditional compilation is particularly useful when maintaining many different versions of the same program. For example, the demo code and full system code could be included in the same program file and controlled by a single #define statement.
Examples
■ This code fragment is a general skeleton for conditional
compilation with #ifdef:
#define DEMO
.
. <statements>
.
#ifdef DEMO
<demo specific statements>
#endif
■ This example controls conditional compilation with an
identifier defined on the compiler command line with the /D option.
In DOS:
C>CLIPPER Myfile /DDEBUG
In the program (.prg) file:
#ifdef DEBUG
Assert(<some condition>)
#endif
■ This example defines a manifest constant to one value if it
does not exist and redefines it to another if it exists:
#ifdef M_MARGIN
#undef M_MARGIN
#define M_MARGIN 15
#else
#define M_MARGIN 10
#endif
identifier is the name of a definition whose absence is being verified.
Description
#ifndef...#endif lets you perform conditional compilation by identifying a section of source code to compile if the specified identifier is undefined.
The #else directive specifies the code to compile if identifier is defined. The #endif terminates the conditional compilation block.
Examples
■ This code fragment is a general skeleton for conditional
compilation with #ifndef:
#define DEBUG
.
. <statements>
.
#ifndef DEBUG
<optimized version of code>
#else
<debugging version of code>
#endif
■ This example compiles a section of code if a specific
identifier is undefined.
In DOS:
C>CLIPPER Myfile
In the program (.prg) file:
#ifndef NODEBUG
Assert(<some condition>)
#endif
■ This example overrides a default definition in the program
(.prg) file using a manifest constant defined on the compiler command
line with the /D option
In DOS:
C>CLIPPER Myfile /DM_MARGIN=10
In the program (.prg) file:
#ifndef M_MARGIN
#define M_MARGIN 15
#endif
headerFileSpec specifies the name of another source file to include in the current source file. As indicated in the syntax, the name must be enclosed in double quotation marks.
headerFileSpec may contain an explicit path and file name as well as a file extension. If, however, no path is specified, the preprocessor searches the following places:
■ Source file directory
■ Directories supplied with the /I option
■ Directories specified in the INCLUDE environment variable
#include directives may be nested up to 15 levels deep—that is, a file that has been included may contain #include directives, up to 15 levels.
Description
#include inserts the contents of the specified file in place of the #include directive in the source file. By convention, the file inserted is referred to as a header file. Header files should contain only preprocessor directives and external declarations. By convention CA-Clipper header files have a .ch extension.
When deciding where to locate your header files, you have two basic choices. You can place them in the source file directory where they are local to the current system; or, you can make them globally available by placing them in the directory specified in the INCLUDE environment variable. A list of one or more directories can be specified.
Header files overcome the one major drawback of defining constants or inline functions—the #define directive only affects the file in which it is contained. This means that every program which needs access to these statements must have a list of directives at the top. The solution to this problem is to place #define statements in a separate file and use the #include directive to tell the preprocessor to include that file before compiling.
For example, suppose the file "Inkey.ch" contains a list of #define directives assigning key values to constants. Instead of including these directives at the top of each program file (.prg) requiring access to them, you can simply place the following line at the top of each program file:
#include "Inkey.ch"
This causes the preprocessor to look for inkey.ch and place all the directives contained within it at the top of this program.
Another advantage of using the #include directive is that all the #define statements are contained in one file. If any modifications to these statements are necessary, only the #include file need be altered; the program itself remains untouched.
Note that the scope of definitions within an included header file is the current program file unless the header file is included on the compiler command line with the /U option. In this case, the scope is all the program files compiled in the current invocation of the compiler.
Notes
■ Supplied header files: CA-Clipper provides a number of header
files containing manifest constants for common operations. Refer to \CLIP53\INCLUDE for more information.
■ std.ch—the standard header file: std.ch is the standard
header file provided with CA-Clipper. Its default location is \CLIP53\INCLUDE. std.ch contains the definitions of all CA-Clipper commands and the standard functions specified as pseudofunctions. It is strongly recommended that no changes be made to std.ch. If changes are desired, it is advisable to copy std.ch to a new name, make the changes, and compile with /U.
This header file differs somewhat from a header file you might #include in that everything defined in std.ch, with #define, #translate, or #command, has a scope of the entire compile rather than the current source file.
Examples
■ This example uses #include to insert inkey.ch, a file of
common keyboard definitions, into a key exception handler called by
an interface function:
#include "Inkey.ch"
FUNCTION GetEvent()
LOCAL nKey, nResult
nKey = Inkey(0)
DO CASE
CASE nKey = K_F10
nResult := DoMenu("Browse")
CASE nKey = K_ESC
nResult := DoQuit()
.
. <statements>
.
CASE nKey = K_CTRL_RIGHT
nResult := DoNextRec()
ENDCASE
RETURN nResult
messageText is the text of the message to display. messageTest is a literal character string. Do not enclose the message in quotation marks unless you want them to appear as part of the display.
Description
#stdout causes the compiler to output the literal text to the standard output device (stdout) during compilation. If messageText is not specified, a carriage return/line feed pair echoes to stdout.
Warning! Manifest constants are not translated in #stdout. Implementation is identical to #error with the following exceptions: output is written to STDOUT and no compiler error is generated.
Examples
This example demonstrates use of #stdout:
#ifdef DEBUG
#stdout Compiling debugging version...
#endif
PROCEDURE Main()
? "Hello world"
RETURN
#stdout End of "Hello World" program
identifier is the name of the manifest constant or pseudofunction to remove.
Description
#undef removes an identifier defined with the #define directive. After an #undef, the specified identifier becomes undefined. Use #undef to remove an identifier before you redefine it with #define, preventing the compiler warning that occurs when an existing identifier is redefined. Also, use #undef to make conditional compilation specific to certain sections of a program.
Examples
■ To define and then undefine a manifest constant and a
pseudofunction:
#define K_ESC 27
#define Max(x, y) IF(x > y, x, y)
.
. <statements>
.
#undef K_ESC
#undef MAX
■ To use #undef to undefine an identifier before redefining it:
#define DEBUG
.
. <statements>
.
#undef DEBUG
#define DEBUG .T.
■ To undefine an identifier if it exists, and otherwise define
it for later portions of the program file:
#ifdef TEST
#undef TEST
#else
#define TEST
#endif
matchPattern is the pattern to match in the input text.
resultPattern is the text produced if a piece of input text matches the matchPattern.
Description
The #xcommand and #xtranslate directives work like #command and #translate except that they overcome the dBASE keyword length limitation. They are significant beyond the first four letters, limited only by available memory. All other rules apply.
The (+) operator performs a number of different operations depending on the data types of the operands:
■ Unary positive sign (numeric): A numeric expression prefaced
with the plus (+) operator performs no operation on the operand except to enforce a higher level of precedence than other numeric operations (except the unary minus).
■ Binary addition sign (numeric, date): If both operands are
numeric, nNumber2 is added to nNumber1 and the result is returned as a numeric value. If either operand is date data type and the other operand numeric data type, the nNumber is added as days to the dDate and a date value is returned.
■ Concatenation (character, memo): If both operands are
character, cString2 (the right operand) is concatenated to cString1 (the left operand) returning a character string.
Examples
■ These examples illustrate the various forms of the + operator:
// Binary addition (numeric)
? 1 + 1 // Result: 2
? 1 + 0 // Result: 1
? 0 + 1 // Result: 1
// Binary addition (date)
? CToD("12/12/88") + 12 // Result: 12/24/88
? 12 + CToD("12/12/88") // Result: 12/24/88
// Concatenation (character)
? "Hi " + "there" // Result: Hi there
The increment operator (++) increases the value of its operand by one. This operator adds one to the value of idVar and assigns the new value to idVar.
The ++ operator can appear before or after idVar. Specifying the operator before idVar increments and assigns the value before idVar is used. This is called prefix notation, and it is the most common usage. Specifying the operator after idVar, postfix notation, increments and assigns the value after idVar is used. Stated differently, postfix notation delays the assignment portion of the operation until the rest of the expression is evaluated, and prefix notation gives the assignment precedence over all other operations in the expression.
If the reference to idVar is ambiguous (i.e., not declared at compile time and not explicitly qualified with an alias), idVar is always assumed to be MEMVAR. You can assign field variables by declaring the field variable name in a FIELD statement or referring to the field name prefaced by the FIELD-> alias or the name of the work area.
Examples
■ This code uses the prefix increment operator in an assignment
statement. Therefore, both variables have the same value when
queried:
nValue := 0
nNewValue := ++nValue
? nNewValue // Result: 1
? nValue // Result: 1
■ In this example, the postfix increment operator increases the
first operand of the multiplication operation by one, making its
value 11; however, the assignment of this new value to the nValue
variable will not take place until the entire expression is
evaluated. Therefore, its value is still 10 when the multiplication
operation occurs, and the result of 11 * 10 is 110. Finally, when
nValue is queried again after the expression is evaluated, the
postfix increment assignment is reflected in its new value, 11.
nValue := 10
? nValue++ * nValue // Result: 110
? nValue // Result: 11
aTarget is the array to which a new element is to be added.
expValue is the value assigned to the new element.
Returns
AAdd() evaluates expValue and returns its value. If expValue is not specified, AAdd() returns NIL.
Description
AAdd() is an array function that increases the actual length of the target array by one. The newly created array element is assigned the value specified by expValue.
AAdd() is used to dynamically grow an array. It is useful for building dynamic lists or queues. A good example of this is the GetList array used by the Get system to hold Get objects. After a READ or CLEAR GETS, GetList becomes an empty array. Each time you execute an @...GET command, the Get system uses AAdd() to add a new element to the end of the GetList array, and then assigns a new Get object to the new element.
AAdd() is similar to ASize() but only adds one element at a time; ASize() can grow or shrink an array to a specified size. AAdd(), however, has the advantage that it can assign a value to the new element, while ASize() cannot. AAdd() may also seem similar to AIns(), but they are different: AIns() moves elements within an array, but it does not change the array's length.
Note: If expValue is another array, the new element in the target array will contain a reference to the array specified by expValue.
Examples
■ These examples demonstrate the effects of multiple invocations
of AAdd() to an array:
aArray := {} // Result: aArray is an empty array
AAdd(aArray, 5) // Result: aArray is { 5 }
AAdd(aArray, 10) // Result: aArray is { 5, 10 }
AAdd(aArray, { 12, 10 }) // Result: aArray is
// { 5, 10, { 12, 10 } }
Abs() returns a number representing the absolute value of its argument. The return value is a positive number or zero.
Description
Abs() is a numeric function that determines the magnitude of a numeric value independent of its sign. It lets you, for example, obtain the difference between two numbers as a positive value without knowing in advance which of the two is larger.
As a formalism, Abs(x) is defined in terms of its argument, x, as follows: if x >= 0, Abs(x) returns x; otherwise, Abs(x) returns the negation of x.
expPrompt is an optional prompt displayed before the input area. The prompt can be an expression of any data type.
idVar is the variable that will hold input from the keyboard. If the specified idVar does not exist or is not visible, a private variable is created.
Description
ACCEPT is a console command and wait state that takes input from the keyboard and assigns it as a character string to the specified variable. When ACCEPT is executed, it first performs a carriage return/linefeed, displays the prompt, and then begins taking characters from the keyboard at the first character position following the prompt. You may input up to 255 characters. When input reaches the edge of the screen, as defined by MaxCol(), the cursor moves to the next line.
ACCEPT supports only two editing keys: Backspace and Return. Esc is not supported. Backspace deletes the last character typed. Return confirms entry and is the only key that can terminate an ACCEPT. If Return is the only key pressed, ACCEPT assigns a null value ("") to idVar.
Examples
■ This example uses ACCEPT to get keyboard input from the user:
LOCAL cVar
ACCEPT "Enter a value: " TO cVar
IF cVar == ""
? "User pressed Return"
ELSE
? "User input:", cVar
ENDIF
nTop, nLeft and nBottom, nRight are the upper- left and lower-right window coordinates. Row values can range from zero to MaxRow() and column values can range from zero to MaxCol().
acMenuItems is an array of character strings to display as the menu items. The individual menu items are later identified by their numeric positions in this array.
alSelectableItems is a parallel array of logical values—one element for each item in acMenuItems—that specify the selectable menu items. Elements can be logical values or character strings. AChoice() will not permit a null string and stops displaying if it encounters one. If the element is a character string, it is evaluated as a macro expression which should evaluate to a logical data type. In either case, a value of false (.F.) means that the corresponding menu item is not available, and a value of true (.T.) means that it is available. If you specify lSelectableItems instead of an array, false (.F.) makes all menu items unavailable and true (.T.) makes all menu items available. By default, all menu items are available for selection.
cUserFunction is the name of a user-defined function that executes when an unrecognizable key is pressed. Specify the function name as a character expression without parentheses or arguments. Note that the behavior of AChoice() is affected by the presence of this argument. Refer to the discussion below for further information.
nInitialItem is the position in the acMenuItems array of the item that will be highlighted when the menu is initially displayed. If you specify an unavailable menu item or no argument at all, the initial menu item is the first selectable item in the array.
nWindowRow is the number of the window row on which the initial menu item will appear. Row numbering begins with zero. By default, the initial menu item appears as close to the top of the window as possible, without leaving any empty rows at the bottom. Thus, if there are enough menu items following the initial one to fill up the window, the initial form will appear on the first row (row zero) of the menu. This function argument is used to control the initial menu appearance when there are more menu items than will fit in the window.
As with all functions, optional arguments are omitted by using a comma instead of the actual argument.
Returns
AChoice() returns the numeric position in the acMenuItems array of the menu item selected. If the selection process is aborted, AChoice() returns zero.
Description
AChoice() is a user interface function that can create various kinds of pop-up menus. Each menu uses an array of character strings as menu items and a parallel array of logical values to determine whether items are selectable. When you invoke AChoice(), the list of menu items is displayed within the specified window coordinates. When the user presses Return, the current item is selected, and AChoice() returns the position of the menu item in acMenuItems. When the user presses Esc, AChoice() aborts and returns zero.
The menu items scroll if the number of items in acMenuItems exceeds the number of rows in the menu window, and the user attempts to move the highlight beyond the top or bottom of the menu window. Note that the highlight does not wrap when you reach the top or bottom of the list of items. Pressing the first letter does, however, wrap the highlight within the set of items whose first letter matches the key you press.
■ Navigating the menu: AChoice() has two modes depending on
whether the cUserFunction argument is specified. If it is not specified the following navigation keys are active:
AChoice() Keys (No User Function)
Key Action
Up arrow Go to previous item
Down arrow Go to next item
Home Go to first item in menu
End Go to last item in menu
Ctrl+Home Go to first item in window
Ctrl+End Go to last item in window
PgUp Go to previous page
PgDn Go to next page
Ctrl+PgUp Go to the first item in menu
Ctrl+PgDn Go to last item in menu
Return Select current item
Esc Abort selection
Left arrow Abort selection
Right arrow Abort selection
First Letter Go to next item beginning with first letter
■ Color: Menu items are displayed in standard color, the
highlight in enhanced color, and the unavailable items in the unselected color. For example, the following color statement
SetColor("W+/N, BG+/B, , , W/N")
displays a menu that is bright white on black, the highlight is bright cyan on blue, and the unavailable menu items are dim white on black.
■ User function: Like the other user interface functions,
AChoice() supports a user function. The user function is specified when you want to nest AChoice() invocations to create hierarchical menus or to redefine keys.
When a user function is specified, AChoice() processes only a limited set of keys automatically. These are listed in the following table. All other keys generate a key exception which passes control to the user function for handling. Control is also passed to the user function when AChoice() goes idle (i.e., when there are no more keys to process).
AChoice() Keys (User Function Specified)
Key Action
Uparrow Go to previous item
Dnarrow Go to next item
Ctrl+Home Go to first item in window
Ctrl+End Go to last item in window
PgUp Go to previous page
PgDn Go to next page
Ctrl+PgUp Go to the first item in menu
Ctrl+PgDn Go to last item in menu
When AChoice() executes the user function, it automatically passes the following three parameters:
- The current AChoice() mode
- The current element in the array of items
- The relative row position within the menu window
The mode indicates the current state of AChoice() depending on the key pressed and the action taken by AChoice() prior to executing the user function. The mode parameter has the following possible values:
AChoice() Modes
Mode Achoice.ch Description
0 AC_IDLE Idle
1 AC_HITTOP Attempt to cursor past top of list
2 AC_HITBOTTOM Attempt to cursor past bottom of list
3 AC_EXCEPT Keystroke exceptions
4 AC_NOITEM No selectable items
After the user function has performed whatever operations are appropriate to the AChoice() mode or LastKey(), it must RETURN a value requesting AChoice() to perform an operation from the following set of actions:
AChoice() User Function Return Values
Value Achoice.ch Action
0 AC_ABORT Abort selection
1 AC_SELECT Make selection
2 AC_CONT Continue AChoice()
3 AC_GOTO Go to the next item whose first character
matches the key pressed
Examples
■ This example uses two literal arrays to specify the menu items
and selection criteria. After the menu is displayed and the user
makes a selection, the name of the selected menu item is displayed:
acMenuItems := {"One", "Two", "-------", "Three"}
alSelectableItems := {.T., .T., .F., .T.}
nPosition := AChoice(10, 10, 12, 15, acMenuItems,;
alSelectableItems)
? acMenuItems[nPosition]
■ This example declares an array of menu items and supplies a
user-defined function which displays a message with each highlighted
choice:
#include "achoice.ch"
#include "inkey.ch"
PROCEDURE Main()
LOCAL acMenuItems[4], cUserFunction, nRetVal
LOCAL nKey, nPos
acMenuItems[1] := "Add"
acMenuItems[2] := "Edit"
acMenuItems[3] := "Delete"
acMenuItems[4] := "Update"
CLS
nPos := AChoice( 10, 10, 13, 15, acMenuItems,;
.T., "cUserFunction" )
DO CASE
CASE nPos == 1
// Put ADD routine here
CASE nPos == 2
// Put EDIT routine here
CASE nPos == 3
// Put DELETE routine here
CASE nPos ==4
// Put UPDATE routine here
ENDCASE
RETURN
FUNCTION cUserFunction( nMode, nCurElement, nRowPos )
LOCAL nRetVal := AC_CONT // Default, Continue
LOCAL nKey := LastKey()
DO CASE
// After all pending keys are processed, display message
CASE nMode == AC_IDLE
DO CASE
CASE nCurElement == 1
@ 22, 5 SAY " Adding "
CASE nCurElement == 2
@ 22, 5 SAY " Editing "
CASE nCurElement == 3
@ 22, 5 SAY " Deleting "
CASE nCurElement == 4
@ 22, 5 SAY " Updating "
ENDCASE
nRetVal := AC_CONT // Continue AChoice()
CASE nMode == AC_HITTOP // Attempt to go past Top
Tone( 100, 3 )
CASE nMode == AC_HITBOTTOM // Attempt to go past
// Bottom
Tone( 100, 3 )
CASE nMode == AC_EXCEPT // Key Exception
DO CASE
CASE nKey == K_RETURN // If RETURN key, select
nRetVal := AC_SELECT
CASE nKey == K_ESC // If ESCAPE key, abort
nRetVal := AC_ABORT
OTHERWISE
nRetVal := AC_GOTO // Otherwise, go to item
ENDCASE
ENDCASE
RETURN nRetVal
■ The next example declares the arrays, specifies a selection
condition for one of the menu items, and supplies a user function:
EXTERNAL Updated
//
FUNCTION MyMenu
LOCAL acMenuItems[4], alSelectableItems[4],;
cUserFunction := "DoIt"
//
acMenuItems[1] := "Add Record"
acMenuItems[2] := "Edit Record"
acMenuItems[3] := "Delete Record"
acMenuItems[4] := "Update Record"
//
alSelectableItems[1] := .T.
alSelectableItems[2] := .T.
alSelectableItems[3] := .T.
alSelectableItems[4] := "!Updated()"
// Selection condition
RETURN AChoice(10, 10, 12, 15, acMenuItems,;
alSelectableItems, cUserFunction)
■ This example uses two arrays to specify menu items and
corresponding action blocks. After the menu is displayed and the
user makes a selection, the AChoice() return value is used to
determine which action block of the aActionItems array is evaluated:
PROCEDURE Main()
LOCAL nChoice
LOCAL aMenuItems := { "Add Record ", ;
"Edit Record ", ;
"Delete Record", ;
"Update Record" }
LOCAL aActionItems := { {|| AddFunc() }, ;
{|| EditFunc() }, ;
{|| DelFunc() }, ;
{|| UpdFunc() } }
nChoice := AChoice( 10, 10, 13, 22, aMenuItems )
IF nChoice == 0
QUIT // ESCAPE was pressed
ENDIF
Eval( aActionItems[nChoice] )
RETURN
AClone() is an array function that creates a complete duplicate of the aSource array. If aSource contains subarrays, AClone() creates matching subarrays and fills them with copies of the values in the aSource subarrays. AClone() is similar to ACopy(), but ACopy() does not duplicate nested arrays.
Examples
■ This example creates an array then duplicates it using
AClone(). The first array is then altered, but the duplicate copy is
unaffected:
LOCAL aOne, aTwo
aOne := { 1, 2, 3 } // Result: aOne is {1, 2, 3}
aTwo := AClone(aOne) // Result: aTwo is {1, 2, 3}
aOne[1] := 99 // Result: aOne is {99, 2, 3}
// aTwo is still {1, 2, 3}
nStart is the starting element position in the aSource array. If not specified, the default value is one.
nCount is the number of elements to copy from the aSource array beginning at the nStart position. If nCount is not specified, all elements in aSource beginning with the starting element are copied.
nTargetPos is the starting element position in the aTarget array to receive elements from aSource. If not specified, the default value is one.
Returns
ACopy() returns a reference to the target array, aTarget.
Description
ACopy() is an array function that copies elements from the aSource array to the aTarget array. The aTarget array must already exist and be large enough to hold the copied elements. If the aSource array has more elements, some elements will not be copied.
ACopy() copies values of all data types including NIL and code blocks. If an element of the aSource array is a subarray, the corresponding element in the aTarget array will contain a reference to the subarray. Thus, ACopy() will not create a complete duplicate of a multidimensional array. To do this, use the AClone() function.
Examples
■ This example creates two arrays, each filled with a value.
The first two elements from the source array are then copied into the
target array:
LOCAL nCount := 2, nStart := 1, aOne, aTwo
aOne := { 1, 1, 1 }
aTwo := { 2, 2, 2 }
ACopy(aOne, aTwo, nStart, nCount)
// Result: aTwo is now { 1, 1, 2 }
nPosition is the position of the target array element to be deleted.
Returns
ADel() returns a reference to the target array, aTarget.
Description
ADel() is an array function that deletes an element from an array. The contents of the specified array element is lost, and all elements from that position to the end of the array are shifted up one element. The last element in the array becomes NIL.
Warning! CA-Clipper implements multidimensional arrays by nesting arrays within other arrays. If the aTarget array is a multidimensional array, ADel() can delete an entire subarray specified by nPosition, causing aTarget to describe an array with a different structure than the original.
Examples
■ This example creates a constant array of three elements, and
then deletes the second element. The third element is moved up one
position, and the new third element is assigned a NIL:
LOCAL aArray
aArray := { 1, 2, 3 } // Result: aArray is
// now { 1, 2, 3 }
ADel(aArray, 2) // Result: aArray is
// now { 1, 3, NIL }
cFilespec is the path specification of files to include in the scan of the DEFAULT directory. It is a standard file specification that can include the wildcard characters * and ?, as well as a drive and path reference. If omitted, the default specification is *.*.
aFilenames is the array to fill with the file names matching cFilespec. Each element contains the file name and extension as a character string in all uppercase letters.
aSizes is the array to fill with the sizes of the corresponding files in the aFilenames array. Each element is a numeric data type.
aDates is the array to fill with the dates of the corresponding files in the aFilenames array. Each element is a date data type.
aTimes is the array to fill with the times of the corresponding files in the aFilenames array. Each element filled contains a character string of the form: hh:mm:ss.
aAttributes is the array to fill with attributes of the corresponding files in the aFilenames array. Each element is a character string. If aAttributes is specified, hidden, system, and directory files are included as well as normal files. If aAttributes is not specified, only normal files are included.
Returns
ADir() returns the number of files matching the directory skeleton described in cFilespec.
Description
ADir() is an array function that performs two basic operations. First, it returns the number of files matching the file specification. Second, it fills a series of arrays with file names, sizes, dates, times, and attributes.
ADir() is a compatibility function and therefore not recommended. It is superseded by the Directory() function which returns all file information in a multidimensional array.
Notes
■ Directories: If you specify the aAttributes argument and
cFilespec is *.*, directories will be included in aFilenames. In the aAttributes array, directories are indicated with an attribute value of "D". If ADir() is executed within a subdirectory, the first two entries of the aFilenames array are "." and "..", the parent and current directory aliases. The date and time of last update are reported for directories, but the size of a directory is always zero.
Examples
■ This example creates an array to hold the names of all .txt
files in the current DEFAULT directory, then uses AEval() to list
them to the console:
LOCAL aFiles[ADir("*.TXT")]
ADir("*.TXT", aFiles)
AEval(aFiles, { |element| QOut(element) })
bBlock is a code block to execute for each element encountered.
nStart is the starting element. If not specified, the default is element one.
nCount is the number of elements to process from nStart. If not specified, the default is all elements to the end of the array.
Returns
AEval() returns a reference to aArray.
Description
AEval() is an array function that evaluates a code block once for each element of an array, passing the element value and the element index as block parameters. The return value of the block is ignored. All elements in aArray are processed unless either the nStart or the nCount argument is specified.
AEval() makes no assumptions about the contents of the array elements it is passing to the block. It is assumed that the supplied block knows what type of data will be in each element.
AEval() is similar to dbEval() which applies a block to each record of a database file. Like dbEval(), AEval() can be used as a primitive for the construction of iteration commands for both simple and complex array structures.
Refer to the Code Blocks section in the "Basic Concepts" chapter of the Programming and Utilities Guide for more information on the theory and syntax of code blocks.
Examples
■ This example uses AEval() to display an array of file names
and file sizes returned from the Directory() function:
#include "Directry.ch"
//
LOCAL aFiles := Directory("*.dbf"), nTotal := 0
AEval(aFiles,;
{ | aDbfFile |;
QOut(PadR(aDbfFile[F_NAME], 10), aDbfFile[F_SIZE]),;
nTotal += aDbfFile[F_SIZE]);
} )
//
?
? "Total Bytes:", nTotal
■ This example uses AEval() to build a list consisting of
selected items from a multidimensional array:
#include "Directry.ch"
//
LOCAL aFiles := Directory("*.dbf"), aNames := {}
AEval(aFiles,;
{ | file | AAdd(aNames, file[F_NAME]) };
)
■ This example changes the contents of the array element
depending on a condition. Notice the use of the codeblock
parameters:
LOCAL aArray[6]
AFill(aArray,"old")
AEval(aArray,;
{|cValue,nIndex| IF(cValue == "old",;
aArray[nIndex] := "new",)})
aFieldNames is the array to fill with field names. Each element is a character string.
aTypes is the array to fill with the type of fields in aFieldNames. Each element is a character string.
aWidths is the array to fill with the widths of fields in aFieldNames. Each element is numeric data type.
aDecimals is the array to fill with the number of decimals defined for fields in aFieldNames. Each element is numeric data type. If the field type is not numeric, the aDecimals element is zero.
Returns
AFields() returns the number of fields or the length of the shortest array argument, whichever is less. If no arguments are specified, or if there is no file in USE in the current work area, AFields() returns zero.
Description
AFields() is an array function that fills a series of arrays (structure attribute arrays) with the structure of the database file currently open, one element in each array per field. AFields() works like ADir(), filling a series of existing arrays with information. To use AFields(), you must first create the arrays to hold the database structure information, each with the same number of elements as the number of fields (i.e. FCount()). Once the structure attribute arrays are created, you can then invoke AFields() to fill the structure arrays with information about each field.
By default, AFields() operates on the currently selected work area. It can operate on an unselected work area if you specify it within an aliased expression (see example below).
AFields() is a compatibility function and therefore is not recommended. It is superseded by dbStruct(), which does not require the existence of any arrays prior to invocation and returns a multidimensional array containing the current database file structure.
Examples
■ This example demonstrates how AFields() and AChoice() can be
used together to create a fields picklist:
USE Sales NEW
PRIVATE aFieldNames[FCount()]
AFields(aFieldNames)
@ 1, 0 TO 10, 10 DOUBLE
nChoice := AChoice(2, 1, 9, 9, aFieldNames)
@ 12, 0 SAY IF(nChoice != 0, aFieldNames[nChoice],;
"None selected")
RETURN
■ This example uses AFields() with an aliased expression to fill
arrays with the structure of Sales.dbf, open in an unselected work
area:
LOCAL aFieldNames, aTypes, aWidths, aDecimals
USE Sales NEW
USE Customer NEW
//
aFieldNames := Sales->(Array(FCount()))
aTypes := Sales->(Array(FCount()))
aWidths := Sales->(Array(FCount()))
aDecimals := Sales->(Array(FCount()))
//
Sales->(AFields(aFieldNames, aTypes, ;
aWidths, aDecimals))
expValue is the value to be placed in each array element. It can be an expression of any valid data type.
nStart is the position of the first element to be filled. If this argument is omitted, the default value is one.
nCount is the number of elements to be filled starting with element nStart. If this argument is omitted, elements are filled from the starting element position to the end of the array.
Returns
AFill() returns a reference to aTarget.
Description
AFill() is an array function that fills the specified array with a single value of any data type (including an array, code block, or NIL) by assigning expValue to each array element in the specified range.
Warning! AFill() cannot be used to fill multidimensional arrays. CA-Clipper implements multidimensional arrays by nesting arrays within other arrays. Using AFill() with a multidimensional array will overwrite subarrays used for the other dimensions of the array.
Examples
■ This example, creates a three-element array. The array is
then filled with the logical value, (.F.). Finally, elements in
positions two and three are assigned the new value of true (.T.):
LOCAL aLogic[3]
// Result: aLogic is { NIL, NIL, NIL }
AFill(aLogic, .F.)
// Result: aLogic is { .F., .F., .F. }
AFill(aLogic, .T., 2, 2)
// Result: aLogic is { .F., .T., .T. }
aTarget is the array into which a new element will be inserted.
nPosition is the position at which the new element will be inserted.
Returns
AIns() returns a reference to the target array, aTarget.
Description
AIns() is an array function that inserts a new element into a specified array. The newly inserted element is NIL data type until a new value is assigned to it. After the insertion, the last element in the array is discarded, and all elements after the new element are shifted down one position.
Warning! AIns() must be used carefully with multidimensional arrays. Multidimensional arrays in CA-Clipper are implemented by nesting arrays within other arrays. Using AIns() in a multidimensional array discards the last element in the specified target array which, if it is an array element, will cause one or more dimensions to be lost. To insert a new dimension into an array, first add a new element to the end of the array using AAdd() or ASize() before using AIns().
Examples
■ This example demonstrates the effect of using AIns() on an
array:
LOCAL aArray
aArray := { 1, 2, 3 } // Result: aArray is
// now { 1, 2, 3 }
AIns(aArray, 2) // Result: aArray is
// now { 1, NIL, 2 }
cMessage is the message text displayed and centered in the alert box. If the message contains one or more semicolons, the text after the semicolons is centered on succeeding lines in the dialog box.
aOptions defines a list of up to 4 possible responses to the dialog box.
Returns
Alert() returns a numeric value indicating which option was chosen. If the Esc key is pressed, the value returned is zero.
Description
The Alert() function creates a simple modal dialog. It is useful in error handlers and other "pause" functions. The user can respond by moving a highlight bar and pressing the Return or SpaceBar keys, or by pressing the key corresponding to the first letter of the option. If aOptions is not supplied, a single "Ok" option is presented.
Alert() is sensitive to the presence or absence of the CA-Clipper full-screen I/O system. If the full-screen system is not present, Alert() uses standard I/O to display the message and options tty-style (i.e., 80-column, without word wrap, each line ended with carriage return/linefeed).
Examples
■ This example demonstrates use of an alert dialog box. First,
the array of options is defined, the Alert() function gets the user's
selection, and finally, the user's choice is handled with a DO
CASE...ENDCASE control structure:
#define AL_SAVE 1
#define AL_CANCEL 2
#define AL_CONT 3
// Define an array of options
aOptions := {"Save", "Don't Save", "Continue"}
// Display the dialog box and get the user's selection
nChoice := Alert("File has changed...", aOptions)
// Handle the user's request
DO CASE
CASE nChoice == AL_SAVE
? "Save"
CASE nChoice == AL_CANCEL
? "Don't Save"
CASE nChoice == AL_CONT
? "Continue"
OTHERWISE
? "Escape"
ENDCASE
//
RETURN
Alias() returns the alias of the specified work area as a character string in uppercase. If nWorkArea is not specified, the alias of the current work area is returned. If there is no database file in USE for the specified work area, Alias() returns a null string ("").
Description
Alias() is a database function that determines the alias of a specified work area. An alias is the name assigned to a work area when a database file is USEd. The actual name assigned is either the name of the database file, or a name explicitly assigned with the ALIAS clause of the USE command.
Alias() is the inverse of the Select() function. Alias() returns the alias name given the work area number, and Select() returns the work area number given the alias name.
■ This example returns the name of the previously selected work
area:
USE File1 NEW ALIAS Test1 nOldArea := Select()USE File2 NEW ALIAS Test2 ? Alias( nOldArea ) // Returns Test1
Remove leading and trailing spaces from a character string
Syntax
AllTrim(<cString>) → cTrimString
Arguments
cString is the character expression to be trimmed.
Returns
AllTrim() returns a character string with leading and trailing spaces removed.
Description
AllTrim() is a character function that removes both leading and trailing spaces from a string. It is related to LTrim() and RTrim() which remove leading and trailing spaces, respectively. The inverse of AllTrim(), LTrim(), and RTrim() are the PadC(), PadL(), and PadR() functions which center, left-justify, or right-justify character strings by padding them with fill characters.
Notes
■ Space characters: The AllTrim() function treats carriage
returns, line feeds, and tabs as space characters and removes these as well.
Examples
■ This example creates a string with both leading and trailing
spaces, and then trims them with AllTrim():
cString := Space(10) + "string" + Space(10)
? Len(cString) // Result: 26
? Len(AllTrim(cString)) // Result: 6
nAction defines what action AltD() performs when invoked. The following is a complete list of nAction values and their actions:
AltD() Actions
Argument Action
None Invokes the debugger if it is enabled
0 Disables Alt+D
1 Enables Alt+D
Other No action
Returns
AltD() always returns NIL.
Description
AltD() performs differently depending on its argument as shown in the table above. For more information on using the debugger, refer to "CA-Clipper Debugger-CLD.LIB" chapter in the Programming and Utilities Guide. Also refer to the "Debugging Your Applications" chapter in the Workbench User Guide.
Examples
■ This example demonstrates a series of manifest constants that
can be used as arguments for AltD() before invoking the debugger
programmatically:
#define ALTD_DISABLE 0
#define ALTD_ENABLE 1
//
AltD(ALTD_ENABLE)
ANNOUNCE is a declaration statement that defines a module identifier. A linker may use this identifier later to satisfy pending module REQUESTs. ANNOUNCE and REQUEST provide a mechanism for managing application modules (.prg files).
Specify ANNOUNCE statements prior to any executable statements in a program file. A source (.prg) file can only have one module identifier; all subsequent ANNOUNCE declarations produce a compiler warning and will be ignored. Module identifiers must be unique and should not duplicate the name of any procedures or user-defined functions in a source (.prg) file.
Examples
■ This example illustrates the ANNOUNCE declaration:
ANNOUNCE CustomInit
INIT PROCEDURE MyInit
? "Hypothetical Industries, Inc."
RETURN
The above program module, CustomInit, should be compiled with the /N
option. Subsequently, the program is addressed in the source code of
another program module through use of the REQUEST statement,
REQUEST CustomInit
which causes the module CustomInit to be linked into the resultant
executable (.EXE) file.
APPEND BLANK is a database command that adds a new record to the end of the current database file and then makes it the current record. The new field values are initialized to the empty values for each data type: character fields are assigned with spaces; numeric fields are assigned zero; logical fields are assigned false (.F.); date fields are assigned CToD(""); and memo fields are left empty.
If operating under a network with the current database file shared, APPEND BLANK attempts to add and then lock a new record. If another user has locked the database file with FLock() or locked LastRec() + 1 with RLock(), NetErr() returns true (.T.). Note that a newly APPENDed record remains locked until you lock another record or perform an UNLOCK. APPEND BLANK does not release an FLock() set by the current user.
Examples
■ This example attempts to add a record to a shared database
file and uses NetErr() to test whether the operation succeeded:
USE Sales SHARED NEW
.
. <statements>
.
APPEND BLANK
IF !NetErr()
<update empty record>...
ELSE
? "Append operation failed"
BREAK
ENDIF
FROMxcFile specifies the name of the source file. You can specify xcFile either as a literal file name or as a character expression enclosed in parentheses. If a file extension is not specified, .dbf is the default input file type. If SDF or DELIMITED is specified, the file extension is assumed to be .txt unless otherwise specified.
FIELDSidField list specifies the list of fields to copy from xcFile. The default is all fields.
scope is the portion of the source database file to APPEND FROM. NEXTnAPPENDs the first n records. RECORDnAPPENDs only record number n from xcFile. The default scope is ALL records in xcFile.
WHILElCondition specifies the set of records meeting the condition from the first record in the source file until the condition fails.
FORlCondition specifies the conditional set of records to APPEND FROM within the given scope.
SDF identifies a System Data Format ASCII file. Records and fields are fixed length.
DELIMITED identifies an ASCII text file where character fields are enclosed in double quotation marks (the default delimiter). Note that delimiters are not required and CA-Clipper correctly APPENDs character fields not enclosed in them. Fields and records are variable length.
DELIMITED WITH BLANK identifies an ASCII text file in which fields are separated by one space and character fields are not enclosed in delimiters.
DELIMITED WITHxcDelimiter identifies a delimited ASCII text file where character fields are enclosed using the specified delimiter. You can specify xcDelimiter as a literal character or as a character expression enclosed in parentheses.
See the tables below for more information regarding the format specification requirements for ASCII text files that you want to APPEND using these arguments.
VIA xcDriver specifies the replaceable database driver (RDD) to use to import the desired data. cDriver is the name of the RDD specified as a character expression. If cDriver is specified as a literal value, it must be enclosed in quotes.
If the VIA clause is omitted, APPEND FROM uses the driver in the current work area. If you specify the VIA clause, you must REQUEST the appropriate RDDs to be linked into the application.
Warning! If the DELIMITED WITH clause is specified on a COPY TO or APPEND FROM command line, it must be the last clause specified.
Description
APPEND FROM adds records to the current database file from an ASCII text file or another database file. Only fields with the same names and types are APPENDed. Fields with the same name from both the current database file and xcFile must be the same data type. If they are not, a runtime error occurs when the APPEND FROM command is invoked.
Any date information in xcFile must be in the format yyyymmdd to be properly APPENDed.
In a network environment, APPEND FROM does not require that the current database file be USEed EXCLUSIVEly or locked with FLock() to perform its operation. As each record is added, CA-Clipper automatically arbitrates contention for the new record.
When you invoke APPEND FROM, CA-Clipper attempts to open xcFile as shared and read-only. If access is denied, APPEND FROM terminates with a runtime error. Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information. No error is raised if you attempt to open a .dbf file that is already open.
This table shows the format specifications for SDF text files:
SDF Text File Format Specifications
File Element Format
Character fields Padded with trailing blanks
Date fields yyyymmdd
Logical fields T or F
Memo fields Ignored
Numeric fields Padded with leading blanks or zeros
Field separator None
Record separator Carriage return/linefeed
End of file marker 1A hex or Chr(26)
This table shows the format specifications for DELIMITED and DELIMITED WITHxcDelimiter ASCII text files:
DELIMITED Text File Format Specifications
File Element Format
Character fields May be delimited, with trailing blanks truncated
Date fields yyyymmdd
Logical fields T or F
Memo fields Ignored
Numeric fields Leading zeros may be truncated
Field separator Comma
Record separator Carriage return/linefeed
End of file marker 1A hex or Chr(26)
This table shows the format specifications for DELIMITED WITH BLANK ASCII text files:
DELIMITED WITH BLANK Text File Format Specifications
File Element Format
Character fields Not delimited, trailing blanks may be truncated
Date fields yyyymmdd
Logical fields T or F
Memo fields Ignored
Numeric fields Leading zeros may be truncated
Field separator Single blank space
Record separator Carriage return/linefeed
End of file marker 1A hex or Chr(26)
Notes
■ Deleted records: If DELETED is OFF, deleted records in
xcFile are APPENDed to the current database file and retain their deleted status. If DELETED is ON, however, none of the deleted xcFile records are APPENDed.
■ Unmatched field widths: If a field in the current database
file is a character type and has a field length greater than the incoming xcFile data, CA-Clipper pads the xcFile data with blanks. If the current field is a character data type and its field length is less than the incoming xcFile data, the xcFile data is truncated to fit. If the current field is a numeric type and the incoming xcFile data has more digits than the current field length, a runtime error occurs.
Examples
■ This example demonstrates an APPEND FROM command using a
fields list and a FOR condition:
USE Sales NEW
APPEND FROM BranchFile FIELDS Branch, Salesman, Amount;
FOR Branch = 100
■ This example demonstrates how a <scope> can be specified to
import a particular record from another database file:
APPEND RECORD 5 FROM Temp
nElements is the number of elements in the specified dimension. The maximum number of elements in a dimension is 4096. Arrays in CA-Clipper can have an unlimited number of dimensions.
Returns
Array() returns an array of specified dimensions.
Description
Array() is an array function that returns an uninitialized array with the specified number of elements and dimensions. If more than one nElements argument is specified, a multidimensional array is created with the number of dimensions equal to the number of nElements arguments specified. Any nElements that is itself an array creates a nested array.
In CA-Clipper, there are several ways to create an array. You can declare an array using a declaration statement such as LOCAL or STATIC; you can create an array using a PRIVATE or PUBLIC statement; you can assign a literal array to an existing variable; or you can use the Array() function. Array() has the advantage that it can create arrays within expressions or code blocks.
Examples
■ This example creates a one-dimensional array of five elements
using the Array() function, and then shows the equivalent action by
assigning a literal array of NIL values:
aArray := Array(5)
aArray := { NIL, NIL, NIL, NIL, NIL }
■ This example shows three different statements which create the
same multidimensional array:
aArray := Array(3, 2)
aArray := { {NIL, NIL}, {NIL, NIL}, {NIL, NIL} }
aArray := { Array(2), Array(2), Array(2) }
■ This example creates a nested, multidimensional array:
aArray := Array(3, {NIL,NIL})
cExp is the character expression to be converted to a number.
Returns
Asc() returns an integer numeric value in the range of zero to 255, representing the ASCII value of cExp.
Description
Asc() is a character conversion function that returns the ASCII value of the leftmost character in a character string. Asc() is used primarily on expressions requiring numeric calculations on the ASCII value of a character. Chr() and Asc() are inverse functions.
expSearch is either a simple value to scan for, or a code block. If expSearch is a simple value it can be character, date, logical, or numeric type.
nStart is the starting element of the scan. If this argument is not specified, the default starting position is one.
nCount is the number of elements to scan from the starting position. If this argument is not specified, all elements from the starting element to the end of the array are scanned.
Returns
AScan() returns a numeric value representing the array position of the last element scanned. If expSearch is a simple value, AScan() returns the position of the first matching element, or zero if a match is not found. If expSearch is a code block, AScan() returns the position of the element where the block returned true (.T.).
Description
AScan() is an array function that scans an array for a specified value and operates like SEEK when searching for a simple value. The expSearch value is compared to the target array element beginning with the leftmost character in the target element and proceeding until there are no more characters left in expSearch. If there is no match, AScan() proceeds to the next element in the array.
Since AScan() uses the equal operator (=) for comparisons, it is sensitive to the status of EXACT. If EXACT is ON, the target array element must be exactly equal to the result of expSearch to match.
If the expSearch argument is a code block, AScan() scans the aTarget array executing the block for each element accessed. As each element is encountered, AScan() passes the element's value as an argument to the code block, and then performs an Eval() on the block. The scanning operation stops when the code block returns true (.T.), or AScan() reaches the last element in the array.
Examples
■ This example demonstrates scanning a three-element array using
simple values and a code block as search criteria. The code block
criteria shows how to perform a case-insensitive search:
aArray := { "Tom", "Mary", "Sue" }
? AScan(aArray, "Mary") // Result: 2
? AScan(aArray, "mary") // Result: 0
//
? AScan(aArray, { |x| Upper(x) ;
== "MARY" }) // Result: 2
■ This example demonstrates scanning for multiple instances of a
search argument after a match is found:
LOCAL aArray := { "Tom", "Mary", "Sue",;
"Mary" }, nStart := 1
//
// Get last array element position
nAtEnd := Len(aArray)
DO WHILE (nPos := AScan(aArray, "Mary", ;
nStart)) > 0
? nPos, aArray[nPos]
//
// Get new starting position and test
// boundary condition
IF (nStart := ++nPos) > nAtEnd
EXIT
ENDIF
ENDDO
■ This example scans a two-dimensional array using a code block.
Note that the parameter aVal in the code block is an array:
LOCAL aArr:={}
CLS
AAdd(aArr,{"one","two"})
AAdd(aArr,{"three","four"})
AAdd(aArr,{"five","six"})
? AScan(aArr, {|aVal| aVal[2] == "four"}) // Returns 2
ASize() returns a reference to the target array, aTarget.
Description
ASize() is an array function that changes the actual length of the aTarget array. The array is shortened or lengthened to match the specified length. If the array is shortened, elements at the end of the array are lost. If the array is lengthened, new elements are added to the end of the array and assigned NIL.
ASize() is similar to AAdd() which adds a single new element to the end of an array and optionally assigns a new value at the same time. Note that ASize() is different from AIns() and ADel(), which do not actually change the array's length.
Note: ASize() only supports single-dimensional arrays.
Examples
■ These examples demonstrate adding new elements and deleting
existing elements:
aArray := { 1 } // Result: aArray is { 1 }
ASize(aArray, 3) // Result: aArray is { 1, NIL, NIL }
ASize(aArray, 1) // Result: aArray is { 1 }
nStart is the first element of the sort. If not specified, the default starting position is one.
nCount is the number of elements to be sorted. If not specified, all elements in the array beginning with the starting element are sorted.
bOrder is an optional code block used to determine sorting order. If not specified, the default order is ascending.
Returns
ASort() returns a reference to the aTarget array.
Description
ASort() is an array function that sorts all or part of an array containing elements of a single data type. Data types that can be sorted include character, date, logical, and numeric.
If the bOrder argument is not specified, the default order is ascending. Elements with low values are sorted toward the top of the array (first element), while elements with high values are sorted toward the bottom of the array (last element).
If the bOrder block argument is specified, it is used to determine the sorting order. Each time the block is evaluated, two elements from the target array are passed as block parameters. The block must return true (.T.) if the elements are in sorted order. This facility can be used to create a descending or dictionary order sort. See the examples below.
When sorted, character strings are ordered in ASCII sequence; logical values are sorted with false (.F.) as the low value; date values are sorted chronologically; and numeric values are sorted by magnitude.
Notes
■ ASort() is only guaranteed to produce sorted output (as
defined by the block), not to preserve any existing natural order in the process.
■ Because CA-Clipper implements multidimensional arrays by
nesting subarrays within other arrays, ASort() will not directly sort a multidimensional array. To sort a nested array, you must supply a code block which properly handles the subarrays.
Examples
■ This example creates an array of five unsorted elements, sorts
the array in ascending order, then sorts the array in descending
order using a code block:
aArray := { 3, 5, 1, 2, 4 }
ASort(aArray)
// Result: { 1, 2, 3, 4, 5 }
ASort(aArray,,, { |x, y| x > y })
// Result: { 5, 4, 3, 2, 1 }
■ This example sorts an array of character strings in ascending
order, independent of case. It does this by using a code block that
converts the elements to uppercase before they are compared:
aArray := { "Fred", Kate", "ALVIN", "friend" }
ASort(aArray,,, { |x, y| Upper(x) < Upper(y) })
■ This example sorts a nested array using the second element of
each subarray:
aKids := { {"Mary", 14}, {"Joe", 23}, {"Art", 16} }
aSortKids := ASort(aKids,,, { |x, y| x[2] < y[2] })
Result:
{ {"Mary", 14}, {"Art", 16}, {"Joe", 23} }
Return the position of a substring within a character string
Syntax
At(<cSearch>, <cTarget>) → nPosition
Arguments
cSearch is the character substring to be searched for.
cTarget is the character string to be searched.
Returns
At() returns the position of the first instance of cSearch within cTarget as an integer numeric value. If cSearch is not found, At() returns zero.
Description
At() is a character function used to determine the position of the first occurrence of a character substring within another string. If you only need to know whether a substring exists within another string, use the $ operator. To find the last instance of a substring within a string, use RAt().
Examples
■ These examples show typical use of At():
? At("a", "abcde") // Result: 1
? At("bcd", "abcde") // Result: 2
? At("a", "bcde") // Result: 0
■ This example splits a character string based on the position
of a comma within the target string:
cTarget := "Langtree, Lilly"
? SubStr(cTarget, 1, At(",", cTarget) - 1)
// Result: Langtree
? SubStr(cTarget, At(",", cTarget) + 2)
// Result: Lilly
ATail() returns either a value or a reference to an array or object. The array is not changed.
Description
ATail() is an array function that returns the highest numbered element of an array. It can be used in applications as shorthand for aArray[Len(aArray)] when you need to obtain the last element of an array.
Examples
■ The following example creates a literal array and returns that
last element of the array:
aArray := {"a", "b", "c", "d"}
? ATail(aArray) // Result: d
Average numeric expressions in the current work area
Syntax
AVERAGE <nExp list> TO <idVar list>
[<scope>] [WHILE <lCondition>] [FOR <lCondition>]
Arguments
nExp list is a list of the numeric values to AVERAGE for each record processed.
TOidVar list identifies a list of receiving variables which will contain the average results. Variables that either do not exist or are not visible are created as private variables. idVar list must contain the same number of elements as nExp list.
scope defines the portion of the current database file to AVERAGE. The default scope is ALL.
WHILElCondition specifies the set of records meeting the condition from the current record until the condition fails.
FORlCondition specifies the conditional set of records to AVERAGE within the given scope.
Description
AVERAGE calculates the average of one or more numeric expressions to variables for a range of records in the current database file. Zero values are counted in the AVERAGE unless explicitly ruled out with a FOR condition.
Examples
■ This example averages a single numeric field using a condition
to select a subset of records from the database file:
USE Sales NEW
AVERAGE Amount TO nAvgAmount FOR Branch = "100"
■ This example finds the average date for a range of dates:
AVERAGE (SaleDate - CToD("00/00/00")) ;
TO nAvgDays FOR !Empty(SaleDate)
dAvgDate := CToD("00/00/00") + nAvgDays
BEGIN SEQUENCE
<statements>...
[BREAK [<exp>]]
<statements>...
[RECOVER [USING <idVar>]]
<statements>...
END [SEQUENCE]
Arguments
BREAKexp branches execution to the statement immediately following the nearest RECOVER statement if one is specified or the nearest END SEQUENCE statement. exp is the value returned into the idVar specified in the USING clause of the RECOVER statement.
RECOVER USINGidVar defines a recover point in the SEQUENCE construct where control branches after a BREAK statement. If USINGidVar clause is specified, idVar receives the value returned by the BREAK statement. In general, this is an error object.
END defines the end point of the SEQUENCE control structure. If no RECOVER statement is specified, control branches to the first statement following the END statement after a BREAK.
Description
BEGIN SEQUENCE...END is a control structure used for exception and runtime error handling. It delimits a block of statements, including invoked procedures and user-defined functions. When a BREAK is encountered anywhere in a block of statements following the BEGIN SEQUENCE statement up to the corresponding RECOVER statement, control branches to the program statement immediately following the RECOVER statement. If a RECOVER statement is not specified, control branches to the statement following the END statement, terminating the SEQUENCE. If control reaches a RECOVER statement without encountering a BREAK, it branches to the statement following the corresponding END.
The RECOVER statement optionally receives a parameter passed by a BREAK statement that is specified with a return value. This is usually an error object, generated and returned by the current error handling block defined by ErrorBlock(). If an error object is returned, it can be sent messages to query information about the error. With this information, a runtime error can be handled within the context of the operation rather than in the current runtime error handler. See the example below.
Within a SEQUENCE construct there are some restrictions on what statements are allowed between the BEGIN SEQUENCE and RECOVER statements. You cannot RETURN, LOOP, or EXIT between a BEGIN SEQUENCE and RECOVER statement. From within the RECOVER statement block, however, you can LOOP, EXIT, BREAK, or RETURN since the SEQUENCE is essentially completed at that point. Using LOOP from within the RECOVER statement block is useful for re-executing the SEQUENCE statement block. See the example below.
SEQUENCE constructs are quite flexible. They can be nested and more than one can be defined in the same procedure or user-defined function. If more than one SEQUENCE construct is specified, each SEQUENCE should delimit one discrete operation.
For more information on error objects, refer to the Error class in this chapter.
Examples
■ This code fragment demonstrates a SEQUENCE construct in which
the BREAK occurs within the current procedure:
BEGIN SEQUENCE
<statements>...
IF lBreakCond
BREAK
ENDIF
RECOVER
<recovery statements>...
END
<recovery statements>...
■ This example demonstrates an error handler returning an error
object to the variable specified in the USING clause of the RECOVER
statement:
LOCAL objLocal, bLastHandler
//
// Save current and set new error handler
bLastHandler := ErrorBlock({ |objErr| ;
MyHandler(objErr, .T.) })
//
BEGIN SEQUENCE
.
. <operation that might fail>
.
RECOVER USING objLocal
//
// Send messages to objLocal and handle the error
? "Error: "
IF objLocal:genCode != 0
?? objLocal:description
ENDIF
.
.
.
END
//
// Restore previous error handler
ErrorBlock( bLastHandler )
FUNCTION MyHandler( objError, lLocalHandler )
//
// Handle locally returning the error object
IF lLocalHandler
BREAK objError
ENDIF
.
. <other statements to handle the error>
.
RETURN NIL
■ This example re-executes a SEQUENCE statement block by LOOPing
from within the RECOVER statement block:
DO WHILE .T.
BEGIN SEQUENCE
.
. <operation that may fail>
.
RECOVER
IF PrintRecover()
LOOP // Repeat the SEQUENCE statement block
ENDIF
END
EXIT // Escape from the operation
ENDDO
Convert a 16-bit signed integer to a numeric value
Syntax
Bin2I(<cSignedInt>) → nNumber
Arguments
cSignedInt is a character string in the form of a 16-bit signed integer number—least significant byte first. Only the first two characters are used by the function; all others are ignored.
Returns
Bin2I() returns an integer numeric value.
Description
Bin2I() is a low-level file function that is used with FRead() to convert a two-byte character string formatted as a signed integer to a CA-Clipper numeric data type. This is most useful when you are reading foreign file types and want to read numeric data in its native format.
Examples
■ This example opens a database file using low-level file
functions and reads the date of last update (bytes 1-3). The result
is the same as with LUpdate():
#include "Fileio.ch"
//
nHandle := FOpen("Sales.dbf", FO_READ)
//
// Point to byte 1 in the file
FSeek(nHandle, 1, FS_SET)
//
// Read date of last update
nYear := Bin2I(FReadStr(nHandle, 1) + Chr(0))
nMonth := Bin2I(FReadStr(nHandle, 1) + Chr(0))
nDay := Bin2I(FReadStr(nHandle, 1) + Chr(0))
//
? LTrim(Str(nMonth)), LTrim(Str(nDay)), LTrim(Str(nYear))
FClose(nHandle)
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/EXAMPLEA.ASM
Convert a 32-bit signed integer to a numeric value
Syntax
Bin2L(<cSignedInt>) → nNumber
Arguments
cSignedInt is a character string in the form of a 32-bit signed integer number—least significant byte first. Only the first four characters are used by the function; all others are ignored.
Returns
Bin2L() returns an integer numeric value.
Description
Bin2L() is a low-level file function that is used with FRead() to convert a four-byte character string formatted as a signed integer to a CA-Clipper numeric data type. This is most useful when you are reading foreign file types and want to read numeric data in its native format.
Examples
■ This example opens a database file using low-level file
functions and reads the number of records (bytes 4-7). The result is
the same as with LastRec():
#include "Fileio.ch"
//
nHandle := FOpen("Sales.dbf", FO_READ)
// Note: Sales.dbf contains 84 records
//
// Point to byte 4
FSeek(nHandle, 4, FS_SET)
//
// Read the number of records
cRecords := Space(4)
FRead(nHandle, @cRecords, 4)
//
? LTrim(Str(Bin2L(cRecords))) // Result: 84
FClose(nHandle)
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/EXAMPLEA.ASM
Convert a 16-bit unsigned integer to a numeric value
Syntax
Bin2W(<cUnsignedInt>) → nNumber
Arguments
cUnsignedInt is a character string in the form of a 16-bit unsigned integer number—least significant byte first. Only the first two characters are used by the function; all others are ignored.
Returns
Bin2W() returns an integer numeric value.
Description
Bin2W() is a low-level file function that is used with FRead() to convert a two-byte character string formatted as an unsigned integer to a CA-Clipper numeric data type. This is most useful when you are reading from a binary file and want to read data in its native format.
Examples
■ This example opens a database file using low-level file
functions and reads the number of bytes per record (bytes 10-11).
The result is the same as with RecSize():
#include "Fileio.ch"
//
nHandle := FOpen("Sales.dbf", FO_READ)
// Note: The length of a record in Sales.dbf is 124
//
// Point to byte 10, the first record size byte
FSeek(nHandle, 10, FS_SET)
//
// Read record size
cRecSize := Space(2)
FRead(nHandle, @cRecSize, 2)
//
? LTrim(Str(Bin2W(cRecSize))) // Result: 124
FClose(nHandle)
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/EXAMPLEA.ASM
nPointer is a pointer to the BLOB data. This pointer can be obtained using BLOBDIRECTPUT(), BLOBDIRECTEXPORT(), or dbFieldInfo(DBS_BLOB_POINTER, nFieldPos).
cTargetFile is the name of the target file where the BLOB data will be written, including an optional drive, directory, and extension. See SETDEFAULT() and SETPATH() for file searching and creation rules. No default extension is assumed.
If cTargetFile does not exist, it is created. If it exists, this function attempts to open the file in exclusive mode and, if successful, the file is written to without warning or error. If access is denied because another process is using the file, for example, NetErr() is set to true (.T.). Concurrency control:and BLOBDIRECTEXPORT()
nMode is a constant defining the copy mode, as shown in the table below:
Copy Mode Constants
Constant Description
BLOB_EXPORT_APPEND Appends to the file
BLOB_EXPORT_OVERWRITE Overwrites the file (this is the default)
Returns
BLOBDIRECTEXPORT() returns true (.T.) if successful; otherwise, it returns false (.F.).
Description
By default, BLOBDIRECTEXPORT() operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
Examples
■ This example extracts an array of pointers from the BLOB
file's root area, then uses one of the pointers to export a picture
to a file:
FUNCTION PUTPIX()
LOCAL cPixFile
LOCAL nPointer
LOCAL aBLOBPtrs
cPixFile := "picture.gif"
// Customer database with a picture of
// each customer stored in a field called Pix
USE Customer NEW VIA "DBFCDX"
// Assumes that the program previously
// stored an array of direct BLOB pointers
// into the root area of the BLOB file.
// The picture that we want is assumed to
// be the second array element.
aBLOBPtrs := BLOBROOTGET()
nPointer := aBLOBPtrs[2]
// Export picture pointed to by nPointer to a file
IF !BLOBDirectExport(nPointer, cPixFile, ;
BLOB_EXPORT_OVERWRITE)
Alert("Export of picture " + cPixFile + ";
failed!")
ELSE
// Code for displaying picture would go here
ENDIF
nPointer is a pointer to the BLOB data. This pointer can be obtained using BLOBDIRECTPUT(), BLOBDIRECTIMPORT(), or dbFieldInfo(DBS_BLOB_POINTER, nFieldPos).
nStart is the starting position in nPointer. If nStart is positive, the starting position is relative to the leftmost character in nPointer. If nStart is negative, it is relative to the rightmost character in nPointer. If nStart is omitted, it is assumed to be 1.
nCount is the number of bytes of data to retrieve beginning at nStart. If nCount is larger than the amount of data stored, excess data is ignored. If omitted, BLOBDIRECTGET() retrieves to the end of the data.
Note: nStart and nCount apply to string data only. They are ignored for any other data types.
Returns
BLOBDIRECTGET() returns the data retrieved from the BLOB file. The data type of the return value depends on the actual data stored. Use ValType() to determine the data type.
Description
BLOBDIRECTGET() retrieves data stored in a BLOB file without the need to reference a particular field in the database file. It is particularly useful when accessing data that is larger than 64 KB (such as memo fields created with the BLOBIMPORT() function).
By default, this function operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
Examples
■ This example illustrates storing setup information in a BLOB
file, then selectively retrieving the stored information:
FUNCTION PutSettings(aColors,;
aPaths, ;
aPassWords)
LOCAL aSettings
RDDSETDEFAULT ( "DBFCDX" )
MEMOSETSUPER ( "DBFCDX" )
USE Setup NEW via "DBFMEMO"
aSettings := {}
AAdd(aSettings, BLOBDIRECTPUT(0, aColors))
AAdd(aSettings, BLOBDIRECTPUT(0, aPaths))
AAdd(aSettings, BLOBDIRECTPUT(0, aPassWords))
BLOBROOTPUT(aSettings)
CLOSE
FUNCTION GETCOLORS()
LOCAL aSettings
LOCAL aColors
USE Setup NEW VIA "DBFMEMO"
aSettings := BLOBROOTGET()
aColors := BLOBDIRECTGET(aSettings[1])
CLOSE
RETURN aColors
nOldPointer is a pointer to the BLOB data which will be released after the import. This pointer can be obtained using BLOBDIRECTPUT(), BLOBDIRECTIMPORT(), or dbFieldInfo(DBS_BLOB_POINTER, nFieldPos). Passing zero (0) disables the release of data.
Important! If specified, BLOBDIRECTIMPORT() releases the space associated with nOldPointer for reuse by other data. Therefore, it is illegal to use nOldPointer with any of the BLOB functions after passing it as an argument to this function. Use the function's return value to refer to the newly stored data.
cSourceFile is the name of the file from which to read the BLOB data, including an optional drive, directory, and extension. See SETDEFAULT() and SETPATH() for file searching and creation rules. No default extension is assumed.
This function attempts to open cSourceFile in shared mode. If the file does not exist, a runtime error is raised. If the file is successfully opened, the operation proceeds. If access is denied because another process has exclusive use of the file, for example, NetErr() is set to true (.T.). Concurrency control:and BLOBDIRECTIMPORT()
Note: There are no restrictions on the size of cSourceFile except that you must have enough disk space to make the copy.
Returns
BLOBDIRECTIMPORT() returns a numeric pointer to the BLOB image stored in cSourceFile.
Description
BLOBDIRECTIMPORT() provides a mechanism for copying the contents of a file into a BLOB file. By default, this function operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
BLOBDIRECTIMPORT() is used in conjunction with BLOBDIRECTEXPORT() to transfer data back and forth between external files and BLOB files. You can use BLOBDIRECTIMPORT() with a variety of file types, including graphic images, word processor files, and printer fonts. These two functions are excellent for creating databases for documents, graphics, sounds, etc.
Important! After importing a file with BLOBDIRECTIMPORT(), nNewPointer, the return value, is the only way to access the data from the BLOB file. It is up to you to provide permanent storage for this reference (see example below).
Note: dbFieldInfo(DBS_BLOB_TYPE, nFieldPos) will return "C" (string) for any memo field created using BLOBDIRECTIMPORT().
Examples
■ This example imports a bitmap (.bmp) file to be part of an
array of startup data. The data, stored in the root area of the BLOB
file, could then be used to display the application's startup screen:
FUNCTION PUTPIX()
LOCAL cBMPFile
LOCAL aSettings
cBMPFile := "logo.bmp"
aSettings := {}
// Customer database where startup parameters
// are stored for convenience
USE Customer NEW VIA "DBFMEMO"
// Get default path settings
AAdd(aSettings, STARTPATHS())
// Get default color settings
AAdd(aSettings, DEFAULTCOLORS())
// Get company logo for display at startup.
// There is nothing to free because this
// is the first time importing.
nPointer := BLOBDIRECTIMPORT(0, cBMPFile)
AAdd(aSettings, nPointer)
// Store the settings in the root area of
// the customer.fpt file
BLOBROOTPUT(aSettings)
nOldPointer is a reference to previously stored BLOB data. This reference can be obtained using BLOBDIRECTPUT(), BLOBDIRECTIMPORT(), or dbFieldInfo(DBS_BLOB_POINTER, nFieldPos). If other than zero (0), the data referenced by nOldPointer is replaced by uBLOB; otherwise, uBLOB is added to the current contents of the BLOB file.
Important! If specified, BLOBDIRECTPUT() releases the space associated with nOldPointer for reuse by other data. Therefore, it is illegal to use nOldPointer with any of the BLOB functions after passing it as an argument to this function. Use the function's return value to refer to the newly stored data.
uBLOB is the data you want to put into the BLOB file. uBLOB can be any CA-Clipper data type except code block or an object.
Returns
BLOBDIRECTPUT() returns a numeric pointer to the uBLOB data.
Description
BLOBDIRECTPUT() stores variable length BLOB data without creating a link with a particular memo field in a database file. After adding data to a BLOB file using BLOBDIRECTPUT(), you should store the function's return value, as this is the only way to access the data from the BLOB file. It is up to you, the developer, to provide permanent storage for this reference (see BLOBROOTPUT()).
By default, this function operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
Examples
■ This example illustrates storing setup information in a BLOB
file, then selectively retrieving the stored information:
FUNCTION PutSettings(aColors,;
aPaths, aPassWords)
LOCAL aSettings
USE Setup NEW VIA "DBFMEMO"
aSettings := {}
AAdd(aSettings, BLOBDIRECTPUT(0, aColors))
AAdd(aSettings, BLOBDIRECTPUT(0, aPaths))
AAdd(aSettings, BLOBDIRECTPUT(0, aPassWords))
BLOBROOTPUT(aSettings)
CLOSE
FUNCTION GETCOLORS()
LOCAL aSettings
LOCAL aColors
USE Setup NEW VIA "DBFMEMO"
aSettings := BLOBROOTGET()
aColors := BLOBDIRECTGET(aSettings[1])
CLOSE
RETURN aColors
nFieldPos is the position of the field in the database file structure.
cTargetFile is the name of the target file where the BLOB data will be written, including an optional drive, directory, and extension. See SETDEFAULT() and SETPATH() for file searching and creation rules. No default extension is assumed.
If cTargetFile does not exist, it is created. If it exists, this function attempts to open the file in exclusive mode and, if successful, the file is written to without warning or error. If access is denied because another process is using the file, for example, NetErr() is set to true (.T.). Concurrency control:and BLOBEXPORT()
nMode is a constant defining the copy mode, as shown in the table below:
Field Information Type Constants
Constant Description
BLOB_EXPORT_APPEND Number of decimal places for the field
BLOB_EXPORT_OVERWRITE Length of the field
Returns
BLOBEXPORT() returns true (.T.) if successful; otherwise, it returns false (.F.).
Description
By default, this function operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
Examples
■ This example exports the contents of a field that stores a
picture to a graphic interchange format (.gif) file, so that the file
can be programmatically displayed:
FUNCTION SHOWPIX()
LOCAL cPixFile := "Picture.gif"
LOCAL nPos
// Customer database with a picture of each
// customer stored in a field called Pix
USE Customer NEW VIA "DBFCDX"
nPos := FieldPos("Pix")
// Export the BLOB file's data
// for the current Pix field
IF !BLOBEXPORT(nPos, cPixFile,;
BLOB_EXPORT_OVERWRITE)
Alert("Export of picture " + cPixFile + ";
failed!")
ELSE
// Code for displaying picture would go here
ENDIF
nFieldPos is the position of the field in the database file structure.
nStart is the starting position in the memo field of the BLOB data. If nStart is positive, the starting position is relative to the leftmost character in nFieldPos. If nStart is negative, it is relative to the rightmost character in nFieldPos. If nStart is omitted, it is assumed to be 1.
nCount is the number of bytes of data to retrieve beginning at nStart. If nCount is larger than the amount of data stored, excess data is ignored. If omitted, BLOBGET() retrieves to the end of the data.
Note: nStart and nCount apply to string data only. They are ignored for any other data types.
Returns
BLOBGET() returns the BLOB data retrieved from the memo field. The data type of the return value depends on the actual data stored. Use ValType() to determine the data type. If the indicated field is not a memo field, BLOBGET() returns NIL.
Description
BLOBGET() is very similar to FieldGet(). However, because string type variables cannot be larger than 64 KB, FieldGet() will raise a runtime error when attempting to retrieve memo fields of this magnitude or greater.
BLOBGET() will also raise an error if you attempt to retrieve a field greater than this magnitude; however, you can retrieve any subset of the BLOB data by using an nCount less than 64 KB.
Note: BLOB data less than 64 KB can be retrieved from a memo field using standard means (for example, referring to the field by name in an expression or using the FieldGet() function).
By default, this function operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
Examples
■ This example imports information from a word processing
document into a field, then uses BLOBGET() to extract the first 25
characters of the field:
FUNCTION GETFIRST25()
LOCAL nPos
LOCAL cStr
USE customer NEW VIA "DBFCDX"
// Field that contains word processor
// documentation
nPos := FieldPos("WP_DOC")
// Import a file (can be larger than 64 KB), then
// obtain the first 25 characters to show to the
// user
IF BLOBImport(nPos, "c:\application\temp.doc")
cStr := BLOBGet(nPos, 1, 25)
ELSE
cStr := "Error: could not import file!"
ENDIF
CLOSE
RETURN cStr
Read the contents of a file as a BLOB, identified by a memo field number
Syntax
BLOBImport(<nFieldPos>, <cSourceFile>) → lSuccess
Arguments
nFieldPos is the position of the field in the database file structure.
cSourceFile is the name of the file from which to read the BLOB data, including an optional drive, directory, and extension. See SETDEFAULT() and SETPATH() for file searching and creation rules. No default extension is assumed.
This function attempts to open cSourceFile in shared mode. If the file does not exist, a runtime error is raised. If the file is successfully opened, the operation proceeds. If access is denied because another process has exclusive use of the file, for example, NetErr() is set to true (.T.). Concurrency control:and BLOBIMPORT()
Note: There are no restrictions on the size of cSourceFile except that you must have enough disk space to make the copy.
Returns
BLOBIMPORT() returns true (.T.) if successful; otherwise, it returns false (.F.).
Description
BLOBIMPORT() provides a mechanism for copying the contents of a file into a memo field as BLOB data. By default, this function operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
BLOBIMPORT() is used in conjunction with BLOBEXPORT() to transfer BLOB data back and forth between files and memo fields. You can use BLOBIMPORT() with a variety of file types, including graphic images, word processor files, and printer fonts. These two functions are excellent for creating databases for documents, graphics, sounds, etc.
Note: dbFieldInfo(DBS_BLOB_TYPE, nFieldPos) will return "C" (string) for any memo field created using BLOBIMPORT().
Examples
■ This example imports information from a word processing
document into a field, and then uses BLOBGET() to extract the first
25 characters of the field:
FUNCTION POPULATE()
USE customer NEW VIA "DBFCDX"
// Construct unique file name based on last
// name and id
DO WHILE .NOT. Eof()
GetPix("Pix", SubStr(LastName, 1, 4) + CustID)
Customer->dbSkip()
ENDDO
FUNCTION GetPix(cPixField, cPixFile)
LOCAL nPos
nPos := FieldPos(cPixField)
// Import the picture file into indicated field
IF !BLOBImport(nPos, cPixFile)
Alert("Import of picture " + cPixFile + ";
failed!")
ENDIF
Retrieve the data from the root area of a BLOB file
Syntax
BLOBROOTGET() → uBLOB
Returns
BLOBROOTGET() returns the data retrieved from the root of the BLOB file. The data type of the return value depends on the actual data stored. Use ValType() or USUALTYPE() to determine the data type. Note that BLOBROOTGET() returns NIL if the root reference has never been written to with BLOBROOTPUT().
Description
BLOBROOTGET() allows the retrieval of a BLOB from the root of a BLOB file in a work area. By default, this function operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
Note: Because the root data does not reference a particular record in the database file, the dbRLock() will not protect this root storage reference. Therefore, if the database file is opened in shared mode, you should use BLOBROOTLOCK() before calling BLOBROOTGET().
Examples
■ This example uses BLOBROOTGET() to read system settings from a
BLOB file into an array, and then demonstrates how to allow the user
to modify the settings and restore them in the BLOB file:
FUNCTION UPDATESETTINGS()
LOCAL aSettings
USE customer NEW SHARED VIA "DBFCDX"
IF BLOBROOTLOCK()
// Get any existing settings
aSettings := BLOBROOTGET()
IF Empty(aSettings)
// This function would populate aSettings
// with default data
aSettings := GETDEFAULTSETTINGS()
ENDIF
// This function would allow the user to
// modify the settings.
IF ModifySettings(aSettings)
// Finally, store the settings
BLOBRootPut(aSettings)
ENDIF
BLOBROOTUNLOCK()
ELSE
aSettings := {}
Alert("Could not obtain a lock on the root;
area")
ENDIF
CLOSE
RETURN aSettings
BLOBROOTLOCK() returns true (.T.) if successful; otherwise, it returns false (.F.).
Description
Use BLOBROOTLOCK() when accessing the database file in shared mode to obtain a lock on the root area of a BLOB file for reading from or writing to the root area.
By default, this function operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
Examples
■ This example illustrates how to properly lock and unlock the
root area of a BLOB file for a database file opened in shared mode:
FUNCTION GETSETTINGS()
LOCAL aCustSettings
// Open a customer file in shared mode
USE customer NEW SHARED DBFCDX
IF BLOBROOTLOCK()
aCustSettings := BLOBROOTGET()
BLOBROOTUNLOCK()
ELSE
Alert("Could not obtain root lock of Customer;
file")
ENDIF
CLOSE
RETURN aCustSettings
uBLOB is the data you want to put into the BLOB file's root area. uBLOB can be any CA-Clipper usual data type except code block and object.
Returns
BLOBROOTPUT() returns true (.T.) if successful; otherwise, it returns false (.F.).
Description
BLOBROOTPUT() allows the storage of one—and only one—piece of data to a BLOB file's root area (there is no size limitation on this one piece of data). After storing the new data, BLOBROOTPUT() releases the space associated with any data previously stored in the BLOB file's root area.
By default, this function operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
Note: Because the root data does not reference a particular record in the database file, the dbRLock() will not protect this root storage reference. Therefore, if the database file is opened in shared mode, you should use BLOBROOTLOCK() before calling BLOBROOTPUT().
Examples
■ This example uses BLOBROOTPUT() to store system settings to a
BLOB file after modification:
FUNCTION UPDATESETTINGS()
LOCAL aSettings
USE customer NEW SHARED VIA "DBFCDX"
IF BLOBROOTLOCK()
// Get any existing settings
aSettings := BLOBROOTGET()
IF Empty(aSettings)
// This function would populate aSettings
// with default data
aSettings := GETDEFAULTSETTINGS()
ENDIF
// This function would allow the user to
// modify the settings.
IF ModifySettings(aSettings)
// Finally, store the settings
BLOBRootPut(aSettings)
ENDIF
BLOBROOTUNLOCK()
ELSE
aSettings := {}
Alert("Could not obtain a lock on the root;
area")
ENDIF
CLOSE
RETURN aSettings
Use BLOBROOTUNLOCK() to release a lock previously obtained using BLOBROOTLOCK().
By default, this function operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
■ This example illustrates how to properly lock and unlock the
root area of a BLOB file for a database file opened in shared mode:
FUNCTION GETSETTINGS()
LOCAL aCustSettings
// Open a customer file in shared mode
USE customer NEW SHARED VIA DBFCDX
IF BLOBROOTLOCK()
aCustSettings := BLOBROOTGET()
BLOBROOTUNLOCK()
ELSE
Alert("Could not obtain root lock of Customer;
file")
ENDIF
CLOSE
RETURN aCustSettings
Bof() returns true (.T.) after an attempt to SKIP backward beyond the first logical record in a database file; otherwise, it returns false (.F.). If there is no database file open in the current work area, Bof() returns false (.F.). If the current database file contains no records, Bof() returns true (.T.).
Description
Bof() is a database function used to test for a boundary condition when you are moving the record pointer backward through a database file using the SKIP command. A simple usage example is a descending order record list with an ascending order index file. A more sophisticated example is a screen paging routine that pages forward or backward through the current database file based on the key the user presses. When the user attempts to page backward, you would use Bof() to test for a beginning of file condition before using the SKIP command to move the record pointer and repaint the screen.
Once Bof() is set to true (.T.), it retains its value until there is another attempt to move the record pointer.
By default, Bof() operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression (see example below).
The SKIP command is the only record movement command that can set Bof() to true (.T.).
Examples
■ This example demonstrates Bof() by attempting to move the
record pointer before the first record:
USE Sales NEW
? RecNo(), Bof() // Result: 1 .F.
SKIP -1
? RecNo(), Bof() // Result: 1 .T.
■ This example uses aliased expressions to query the value of
Bof() in unselected work areas:
USE Sales NEW
USE Customer NEW
USE Invoices NEW
? Sales->(Bof()), Customer->(Bof())
exp is the value passed to the RECOVER clause, if any. Note that exp is not optional. NIL may be specified if there is no break value.
Returns
Break() always returns NIL.
Description
The Break() function is identical in functionality to the BREAK statement. The function must be executed during a SEQUENCE. Break() has the advantage that, as an expression, it can be executed from a code block.
Examples
■ This example illustrates exiting a SEQUENCE from a code block:
bSave := ErrorBlock( {|x| Break(x)} )
BEGIN SEQUENCE
.
.
.
RECOVER USING objError
.
.
.
END
ErrorBlock(bSave)
nTop, nLeft, nBottom, and nRight define the window coordinates. If not specified, the default window coordinates are 1, 0 to MaxRow(), and MaxCol().
Returns
Browse() returns false (.F.) if there is no database file in use; otherwise, it returns true (.T.).
Description
Browse() is a user interface function that invokes a general purpose table-oriented browser and editor for records in the current work area. For a list of the navigation keys which are used by Browse(), refer to the dbEdit() function. Note that Browse() is a compatibility function. dbEdit() should be used in its place. For a more complicated Browse(), TBrowse() should be used.
Notes
■ Status line: Browse() supports a status line in the upper
right corner of the browse window indicating one of the following:
Browse() Status Line Messages
Message Meaning
<new> Append mode
<bof> Top of file
<delete> Current record is deleted
Record Record number display
■ Browse() has the following three modes:
- Browsing: This is the default mode of Browse(). Pressing any
dbEdit() navigation key moves the highlight to a new column or row.
- Field edit: Pressing Return on any field enters field edit
using a GET. Pressing Return terminates the edit mode, saving the changes. Esc terminates without saving changes. Since the field edit mode uses GET, all navigation and editing keys are READ keys.
- Append: GOing BOTTOM with Ctrl+PgDn and then pressing Down
arrow enters append mode with the indicating message "new" on the status line. A new blank record is then inserted. Pressing Up arrow terminates the append mode, saving the new record if data has been entered. If no data has been entered, the new record is not saved.
Examples
■ This is an example of browsing a file:
USE File1 NEW
Browse()
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/BROWSE.PRG
idProcedure is the name of the external procedure to CALL.
WITHexp list is an optional list of up to seven expressions of any data type to pass to the external procedure.
Description
CALL executes a separately compiled or assembled procedure. The procedure must be defined as FAR and end with a FAR return instruction. Place parameters on the stack using the C parameter passing convention. Each parameter consists of a FAR (four-byte) pointer to the actual parameter value. When necessary you may use the Word() function to pass a two-byte binary value in the WITH expression. The DX:BX and ES:BX registers also contain a copy of the first four bytes of parameter information.
The procedure must preserve the BP, SS, SI, DI, ES, and DS registers as well as clear the direction flag.
CALL is a compatibility command and therefore not recommended. It is superseded by the Extend system which provides functions for passing data to and from CA-Clipper.
Notes
■ Character strings: Pass a character argument as a FAR pointer
to a null-terminated string (a string with a 00 hex byte at the end).
■ Numeric values: Pass each numeric argument as a FAR pointer
to an eight-byte IEEE floating point value. To pass a parameter as an integer, use the Word() function. The Word() function converts the numeric value to a two-byte binary integer, and passes the integer value directly rather than through a pointer. Note that Word() will not work for values outside of the ▒32,767 range since these values cannot be accurately represented as two-byte integers.
■ Date values: Pass each date argument as a FAR pointer to a
four-byte (long) integer containing a Julian day number.
■ Logical values: Pass each logical argument as a FAR pointer
to a two-byte binary integer containing zero for false (.F.) and one for true (.T.) .
■ Compiling and linking: CALLed programs must conform to the
following rules:
- Procedures must be in INTEL 8086 relocatable object file
format with the .OBJ file extension.
- Procedures must follow the C calling and parameter passing
conventions.
- Procedures must be available to the linker at link time, along
with the library of the source compiler. You will need runtime support for any language other than assembly language. See your compiler manual for further information.
■ Screen position: When using a CALL statement to access a C or
Assembler routine, the cursor is set to the current screen position within the C or Assembler routine.
■ Microsoft C: Microsoft C versions 5.0 and above place a
leading underscore on function names when they are compiled. To call them, therefore, you must CALL _function.
■ dBASE III PLUS: To convert a dBASE III PLUS load module to a
CA-Clipper-compatible module, add the following statements to your .asm file:
PUBLICproc
and
push ds mov ds, dx
Warning! Modifying the parameter values may produce incorrect or unexpected results and, therefore, is strongly discouraged.
CANCEL and QUIT both terminate the current program, closing all open files, and returning control to the operating system. You can use either command from anywhere in a CA-Clipper program system. A RETURN executed at the highest level procedure performs the same action. Note that CANCEL is a compatibility command. QUIT should be used in its place.
Notes
■ Return code: When a CA-Clipper program terminates, the return
code is set to 1 if the process ends with a fatal error. If the process ends normally, the return code is set to 0 or the last ErrorLevel() set in the program.
Convert a date value to a character day of the week
Syntax
CDoW(<dExp>) → cDayName
Arguments
dExp is the date value to convert.
Returns
CDoW() returns the name of the day of the week as a character string. The first letter is uppercase and the rest of the string is lowercase. For a null date value, CDoW() returns a null string ("").
Description
CDoW() is a date conversion function used in formatting date displays for reports, labels, and screens.
Create check boxes, which are controls that can be toggled on or off by a user
Description
Check boxes present a choice to the user which can be either on or off. When a check box is clicked, its state is toggled (as indicated by an X in the box) between checked (on) and unchecked (off).
The CheckBox class has been designed to be easily integrated into the standard CA-Clipper GET/READ system in addition to providing the necessary functionality to be utilized on its own.
Methods link
Class Function
CheckBox() Create a new CheckBox object
CheckBox(nRow, nColumn,
[,cCaption]) → oCheckBox
Arguments
nRow is a numeric value that indicates the screen row of the check box.
nColumn is a numeric value that indicates the screen column of the check box.
nCaption is an optional character string that describes the check box on the screen. If omitted, the default is an empty string.
Returns
Returns a CheckBox object when all of the required arguments are present; otherwise, CheckBox() returns NIL.
Exported Instance Variables
bitmaps An array of bitmap files to be displayed
bitmaps (Assignable)
Contains an array of exactly two elements that indicates the bitmap files to be displayed. The first element indicates the file name of the bitmap to be displayed when the check box is selected. The second element indicates the file name of the bitmap to be displayed when the check box is not selected.
Drive and directory names are not allowed; the file name extension is required. A bitmap file can be stored as a file on disk or in a bitmap library. If stored as a file, the file must reside in the same directory as the application. If stored in a bitmap library, the library must reside in the same directory as the application and it also must have the same name as the application with a .bml extension.
CA-Clipper will search for the file name first, and if it is not found, then search in the bitmap library. If no file is found either on disk or in the library, no bitmap will be displayed.
If this instance variable is not used, and the application is running in graphic mode, the files CHECK_F.BMU and CHECK_E.BMU will be used for the selected bitmap and unselected bitmap, respectively.
This instance variable only affects applications running in graphic mode and is ignored in text mode.
buffer Logical value indicating checked or unchecked
buffer
Contains a logical value that indicates whether the check box is checked or unchecked. A value of true (.T.) indicates that it is checked and a value of false (.F.) indicates that it is not checked.
capCol Numeric value indicating screen column
capCol (Assignable)
Contains a numeric value that indicates the screen column where the check box's caption is displayed.
capRow Numeric value indicating screen row
capRow (Assignable)
Contains a numeric value that indicates the screen row where the check box's caption is displayed.
caption Character string describing the check box
caption (Assignable)
Contains an optional character string that concisely describes the check box on the screen. If omitted, the default is an empty string.
When present, the & character specifies that the character immediately following it in the caption is the check box's accelerator key. The accelerator key provides a quick and convenient mechanism for the user to move input focus from one data input control to the check box. The user performs the selection by pressing the Alt key in combination with an accelerator key. The case of an accelerator key is ignored.
cargo User-definable variable
cargo (Assignable)
Contains a value of any type that is ignored by the CheckBox object. CheckBox:cargo is provided as a user-definable slot allowing arbitrary information to be attached to a CheckBox object and retrieved later.
col Numeric value indicating screen column
col (Assignable)
Contains a numeric value that indicates the screen column where the check box is displayed.
colorSpec Character string indicating color attributes
colorSpec (Assignable)
Contains a character string that indicates the color attributes that are used by the check box's display() method. The string must contain four color specifiers.
Note: In graphic mode, colorSpec positions 1 and 2 have no affect and are ignored.
CheckBox Color Attributes
Position Applies To Default Value from System
in colorSpec Color setting
1 The check box when it does Unselected
not have input focus
2 The check box when it has Enhanced
input focus
3 The check box's caption Standard
4 The check box caption's Background
accelerator key
Note: The colors available to a DOS application are more limited than those for a Windows application. The only colors available to you here are those listed in the drop-down list box of the Workbench Properties window for that item.
fBlock Code block evaluated at each input focus change
fBlock (Assignable)
Contains an optional code block that, when present, is evaluated each time the CheckBox object receives or loses input focus. The code block takes no implicit arguments. Use CheckBox:hasFocus to determine if the check box is receiving or losing input focus. A value of true (.T.) indicates that it is receiving input focus; otherwise, a value of false (.F.) indicates that it is losing input focus.
This code block is included in the CheckBox class to provide a method of indicating when an input focus change event has occurred. The name "fBlock" refers to focus block.
hasFocus Logical value indicating the input focus
hasFocus
Contains a logical value that indicates whether the CheckBox object has input focus. CheckBox:hasFocus contains true (.T.) if it has input focus; otherwise, it contains false (.F.).
message Character string describing check box
message (Assignable)
Contains a character string that describes the check box. It is displayed on the screen's status bar line.
row Numeric value indicating screen row
row (Assignable)
Contains a numeric value that indicates the screen row where the check box is displayed.
sBlock Code block evaluated at every state change
sBlock (Assignable)
Contains an optional code block that, when present, is evaluated each time the CheckBox object's state changes. The code block takes no implicit arguments. Use the buffer instance variable to determine if the check box is being checked or unchecked. A value of true (.T.) indicates that it is being checked; otherwise, a value of false (.F.) indicates that it is being unchecked.
This code block is included in the CheckBox class to provide a method of indicating when a state change event has occurred. The name "sBlock" refers to state block.
style Character string indicating delimiter characters
style (Assignable)
Contains a character string that indicates the delimiter characters that are used by the check box's display() method. The string must contain four characters. The first is the left delimiter. Its default value is the left square bracket ([) character. The second is the checked indicator. Its default value is the square root character. The third is the unchecked indicator. Its default is the space character (" "). The fourth character is the right delimiter. Its default value is the right square bracket (]) character.
Note: The style instance variable is ignored in graphic mode.
typeOut Logical value false (.F.)
typeOut
Contains the logical value false (.F.). CheckBox:typeOut never changes. It is not used by the CheckBox object and is only provided for compatibility with the other GUI control classes.
Exported Methods
display() Shows a check box and caption on the screen
oCheckBox:display() → self
display() is a method of the CheckBox class that is used for showing a check box and its caption on the screen. display() uses the values of the following instance variables to correctly show the check box in its current context in addition to providing maximum flexibility in the manner a check box appears on the screen: buffer, caption, capCol, capRow, col, colorSpec, hasFocus, row, and style.
HitTest() Indicates position of mouse cursor relative to check box
oCheckBox:hitTest(nMouseRow, nMouseCol)
→ nHitStatus
nMouseRow is a numeric value that indicates the current screen row position of the mouse cursor.
nMouseCol is a numeric value that indicates the current screen column position of the mouse cursor.
Returns a numeric value that indicates the relationship of the mouse cursor with the check box. HitTest() is a method of the CheckBox class that is used for determining if the mouse cursor is within the region of the screen that the check box or its caption occupies.
Applicable Hit Test Return Values
Value Constant Description
0 HTNOWHERE The mouse cursor is not within the region of
the screen that the check box occupies
-1025 HTCAPTION The mouse cursor is on the check box's caption
-2049 HTCLIENT The mouse cursor is on the check box
Button.ch contains manifest constants for the HitTest() return value.
killFocus() Takes input focus away from the CheckBox object
oCheckBox:killFocus() → self
killFocus() is a method of the CheckBox class that is used for taking input focus away from a CheckBox object. Upon receiving this message, the CheckBox object redisplays itself and, if present, evaluates the code block within its fBlock variable.
This message is meaningful only when the CheckBox object has input focus.
Select() Determines whether check box should be checked
oCheckBox:select([lNewState]) → self
lNewState is a logical value that indicates whether the check box should be checked or not. Set to true (.T.) to check the box or false to uncheck the box. If omitted, the check box state will toggle to its opposing state.
Select() is a method of the CheckBox class that is used for changing the state of a check box. Its state is typically changed when the space bar is pressed or the mouse's left button is pressed when its cursor is within the check box's region of the screen.
setFocus() Gives input focus to the CheckBox object
oCheckBox:setFocus() → self
setFocus() is a method of the CheckBox class that is used for giving focus to a CheckBox object. Upon receiving this message, the CheckBox object redisplays itself and if present, evaluates the code block within its fBlock variable.
This message is meaningful only when the CheckBox object does not have input focus.
Examples
■ This example creates and integrates a check box within a Get
List and activates it by performing a READ:
STORE SPACE (25) TO Name
STORE .T. TO Married
STORE SPACE (19) TO Phone
CLS
@ 5,10 SAY "Customer Name: " GET Name
@ 7,10 SAY "Married?: " GET Married CHECKBOX
@ 9,10 SAY "Home Phone: " GET Phone
READ
? ALLTRIM (Name) + " IS " + IIF(Married,"","NOT") + "Married."
WAIT
nCode is an ASCII code in the range of zero to 255.
Returns
Chr() returns a single character value whose ASCII code is specified by nCode.
Description
Chr() is a numeric conversion function that converts an ASCII code to a character. It is the inverse of Asc(). Chr() serves a number of common tasks including:
■ Sending control codes and graphics characters to the screen or
■ The null character: Chr(0) has a length of one (1) and is
treated like any other character. This lets you send it to any device or file, including a database file.
Examples
■ These examples illustrate Chr() with various arguments:
? Chr(72) // Result: H
? Chr(Asc("A") + 32) // Result: a
? Chr(7) // Result: bell sounds
■ These lines of code show the difference between a null string
and the null character:
? Len("") // Result: 0
? Len(Chr(0)) // Result: 1
Close files and release public and private variables
Syntax
CLEAR ALL
Description
CLEAR ALL releases all public and private variables, closes all open databases and related files in all active work areas, and SELECTs work area 1. Related files are index, alternate, and memo files. CLEAR ALL, however, does not release local or static variables.
CLEAR ALL is a compatibility command and therefore not recommended. Its usage in CA-Clipper is superseded by the command or function that performs the specific action you need. You can close files associated with work areas with one of the various forms of the CLOSE command. You can release private and public variables using the RELEASE command although explicitly releasing variables is discouraged in most instances. For more information on the scope and lifetime of variables, refer to the "Basic Concepts" chapter in the Programming and Utilities Guide.
Release Get objects from the current GetList array
Syntax
CLEAR GETS
Description
CLEAR GETS explicitly releases all Get objects in the current and visible GetList array, and terminates the calling READ, releasing any remaining objects in the calling READ, if executed within a SET KEY procedure or a user-defined function invoked by a VALID clause. CLEAR GETS releases Get objects by assigning an empty array to the variable GetList. GetList is the name of the variable used to hold an array of Get objects for subsequent READ commands. There are two other mechanisms that automatically release Get objects: CLEAR specified without the SCREEN clause, and READ specified without the SAVE clause.
CLEAR GETS has two basic uses. First, it can be used to terminate a READ from a SET KEY procedure or VALID user-defined function. Second, it can be used to delete Get objects from the GetList array when you have not executed a READ or you have saved the Get objects by using READ SAVE.
CLEAR MEMORY deletes both public and private memory variables from the memory variable table. It operates in contrast to RELEASE ALL, which does not actually delete public and private memory variables but assigns NIL to those whose scope is the current procedure. CLEAR MEMORY is the only way to delete all public memory variables from current memory. Local and static variables, however, are unaffected by CLEAR MEMORY.
For more information on variables, refer to the Variables section of the "Basic Concepts" chapter in the Programming and Utilities Guide.
SCREEN suppresses the automatic releasing of Get objects from the current and visible GetList array when the screen is CLEARed.
Description
CLEAR is a full-screen command that erases the screen, releases pending GETs, and positions the cursor at row and column zero. If the SCREEN clause is specified, Get objects are not released.
CLS is a synonym for CLEAR SCREEN.
Notes
■ SET KEY and VALID: If you are editing GETs, executing a CLEAR
within a SET KEY procedure or within a VALID user-defined function will abort the active READ when control returns. To clear the screen without CLEARing GETs, use either the CLEAR SCREEN or CLS commands.
CLEAR TYPEAHEAD is a keyboard command that clears all pending keys from the CA-Clipper keyboard buffer. This is useful in user interface procedures or user-defined functions to guarantee that keys processed from the keyboard buffer are appropriate to the current activity and not pending from a previous activity. User functions called by AChoice() and dbEdit() are especially sensitive to such keys.
Note that both the SET TYPEAHEAD and KEYBOARD commands also clear the keyboard buffer.
Examples
■ This example empties the keyboard buffer before invoking
dbEdit(), guaranteeing that any pending keys will not be executed:
CLEAR TYPEAHEAD
dbEdit()
CLOSE [<idAlias> | ALL | ALTERNATE | DATABASES |
FORMAT | INDEXES]
Arguments
idAlias specifies the work area where all files are to be closed.
ALL closes alternate, database, and index files in all work areas, releasing all active filters, relations, and format definitions.
ALTERNATE closes the currently open alternate file, performing the same action as SET ALTERNATE TO with no argument.
DATABASES closes all open databases, memo and associated index files in all work areas, and releases all active filters and relations. It does not, however, have any effect on the active format.
FORMAT releases the current format, performing the same action as SET FORMAT TO with no argument.
INDEXES closes all index files open in the current work area.
Description
CLOSE is a general purpose command that closes various types of CA-Clipper files depending on the specified option. CLOSE with no option closes the current database and associated files, the same as USE with no arguments.
In CA-Clipper, a number of other commands also close files including:
CMonth() returns the name of the month as a character string from a date value with the first letter uppercase and the rest of the string lowercase. For a null date value, CMonth() returns a null string ("").
Description
CMonth() is a date conversion function useful for creating formatted date strings that can be used in reports, labels, or screens.
Examples
■ These examples illustrate CMonth():
? CMonth(Date()) // Result: September
? CMonth(Date() + 45) // Result: October
? CMonth(CToD("12/01/94")) // Result: December
? SubStr(CMonth(Date()), 1, 3) +;
Str(Day(Date())) // Result: Sep 1
Col() returns an integer numeric value. The range of the return value is zero to MaxCol().
Description
Col() is a screen function that returns the current column position of the cursor. The value of Col() changes whenever the cursor position changes on the screen. Both console and full-screen commands can change the cursor position. In addition, Col() is automatically set to zero whenever a CLEAR, CLEAR SCREEN, or CLS command is executed.
Use Col() to position the cursor to a column relative to the current column. It is generally used in combination with Row() and all variations of the @ command. In particular, use Col() and Row() to create screen position-independent procedures or functions that pass the upper-left row and column as parameters.
If DEVICE is SET TO PRINTER, all the output of @...SAY commands is directed to the printer and PRow() and PCol() are updated instead of Row() and Col(). Use these functions when you need to determine the position of the printhead.
Examples
■ This example displays a Customer name beginning at column 10.
The customer's account status is then displayed to the right of the
last character of the customer name using Col():
USE Sales NEW
CLS
@ 1, 10 SAY "Customer Name: " + Trim(Customer)
@ Row(), Col() + 1 SAY "Account status: " + Status
nColorIndex is a number corresponding to the ordinal positions in the current list of color attributes, as set by SetColor().
Returns
Always returns NIL.
Description
ColorSelect() activates the specified color pair from the current list of color attributes (established by SetColor()). Manifest constants for nColorIndex are defined in color.ch.
Color.ch constants
Constant Value
CLR_STANDARD 0
CLR_ENHANCED 1
CLR_BORDER 2
CLR_BACKGROUND 3
CLR_UNSELECTED 4
ColorSelect() does not alter the current SET Color setting.
This table describes the scope of the CA-Clipper color settings affected by SetColor():
Color settings
Setting Scope
Standard All screen output commands and functions
Enhanced GETs and selection highlights
Border Screen border (not supported on EGA and VGA monitors)
Background Not supported
Unselected Unselected GETs
Examples
■ This example demonstrates use of ColorSelect() with the
color.ch manifest constants:
USE Sales NEW
? SetColor() // displays "W/B,N/B,W/N,W/N,W/N"
// in white on blue
ColorSelect(CLR_ENHANCED) // enhanced is active color pair
? "I'm black and blue" // displayed in black on blue
ColorSelect(CLR_STANDARD) // restore standard color
Perform a solid-disk write for all active work areas
Syntax
COMMIT
Description
COMMIT is a database command that flushes CA-Clipper buffers and performs a solid-disk write for all work areas with open database and index files. The solid-disk write capability is available under DOS version 3.3 and above. Under DOS 3.2 or less, COMMIT flushes CA-Clipper buffers to DOS.
In a network environment, issuing a GO TORecNo() or a SKIP0 will flush CA-Clipper's database and index buffers, but only a COMMIT will flush the buffers and perform a solid-disk write. Thus to insure updates are visible to other processes, you must issue a COMMIT after all database update commands (e.g., APPEND, REPLACE). To insure data integrity, COMMIT should be issued before an UNLOCK operation. Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information on update visibility.
Notes
■ COMMIT uses DOS interrupt 21h function 68h to perform the
solid-disk write. It is up to the network operating system to properly implement this request. Check with the network vendor to see if this is supported.
Examples
■ In this example, COMMIT forces a write to disk after a series
of memory variables are assigned to field variables:
USE Sales EXCLUSIVE NEW
MEMVAR->Name := Sales->Name
MEMVAR->Amount := Sales->Amount
//
@ 10, 10 GET MEMVAR->Name
@ 11, 10 GET MEMVAR->Amount
READ
//
IF Updated()
APPEND BLANK
REPLACE Sales->Name WITH MEMVAR->Name
REPLACE Sales->Amount WITH MEMVAR->Amount
COMMIT
ENDIF
CONTINUE is a database command that searches from the current record position for the next record meeting the most recent LOCATE condition executed in the current work area. It terminates when a match is found or end of file is encountered. If CONTINUE is successful, the matching record becomes the current record and Found() returns true (.T.); if unsuccessful, Found() returns false (.F.).
Each work area may have an active LOCATE condition. In CA-Clipper, a LOCATE condition remains pending until a new LOCATE condition is specified. No other commands release the condition.
Notes
■ Scope and WHILE condition: Note that the scope and WHILE
condition of the initial LOCATE are ignored; only the FOR condition is used with CONTINUE. If you are using a LOCATE with a WHILE condition and want to continue the search for a matching record, use SKIP and then repeat the original LOCATE statement adding REST as the scope.
Examples
■ This example scans records in Sales.dbf for a particular
salesman and displays a running total sales amounts:
LOCAL nRunTotal := 0
USE Sales NEW
LOCATE FOR Sales->Salesman = "1002"
DO WHILE Found()
? Sales->Salesname, nRunTotal += Sales->Amount
CONTINUE
ENDDO
■ This example demonstrates how to continue if the pending
LOCATE scope contains a WHILE condition:
LOCAL nRunTotal := 0
USE Sales INDEX Salesman NEW
SEEK "1002"
LOCATE REST WHILE Sales->Salesman = "1002";
FOR Sales->Amount > 5000
DO WHILE Found()
? Sales->Salesname, nRunTotal += Sales->Amount
SKIP
LOCATE REST WHILE Sales->Salesman = "1002";
FOR Sales->Amount > 5000
ENDDO
COPY FILE <xcSourceFile> TO <xcTargetFile>|<xcDevice>
Arguments
xcSourceFile is the name of the source file to copy including the extension.
xcTargetFile is the name of the target file including the extension.
Both arguments can be specified as literal file names or as character expressions enclosed in parentheses. COPY FILE supplies no default extensions.
xcDevice is the name of the device where all subsequent output will be sent. You can specify a device name as a literal character string or a character expression enclosed in parentheses. Additionally, a device can be either local or network. If you COPY TO a non-existing device, you create a file with the name of the device. When specifying device names, do not use a trailing colon.
Description
COPY FILE is a file command that copies files to and from the CA-Clipper default drive and directory unless you specify a drive and/or path. If the xcTargetFile exists, it is overwritten without warning or error.
Examples
■ This example copies a file to a new file and then tests for
the existence of the new file:
COPY FILE Test.prg TO Real.prg
? FILE("Real.prg") // Result: .T.
Copy the current .dbf structure to a new database (.dbf) file
Syntax
COPY STRUCTURE [FIELDS <idField list>]
TO <xcDatabase>
Arguments
FIELDSidField list defines the set of fields to copy to the new database structure in the order specified. The default is all fields.
TOxcDatabase is the name of the target database file and can be specified either as a literal database file name or as a character expression enclosed in parentheses. The default extension is .dbf unless another is specified.
Description
COPY STRUCTURE is a database command that creates an empty database file with field definitions from the current database file. If xcDatabase exists, it is overwritten.
COPY STRUCTURE creates empty structures that can be used to archive records from the current database file or to create a temporary database file for data entry.
Examples
■ In this example, COPY STRUCTURE creates a temporary file.
After the user enters data into the temporary file, the master
database file is updated with the new information:
USE Sales NEW
COPY STRUCTURE TO Temp
USE Temp NEW
lMore := .T.
DO WHILE lMore
APPEND BLANK
@ 10, 10 GET Temp->Salesman
@ 11, 11 GET Temp->Amount
READ
IF Updated()
SELECT Sales
APPEND BLANK
REPLACE Sales->Salesman WITH Temp->Salesman
REPLACE Sales->Amount WITH Temp->Amount
SELECT Temp
ZAP
ELSE
lMore := .F.
ENDIF
ENDDO
CLOSE DATABASES
TOxcExtendedDatabase is the name of the target structure extended database file. This argument can be specified either as a literal database file name or as a character expression enclosed in parentheses.
Description
COPY STRUCTURE EXTENDED creates a database file whose contents is the structure of the current database file with a record for the definition of each field. The structure extended database file has the following structure:
Structure of an Extended File
Field Name Type Length Decimals
1 Field_name Character 10
2 Field_type Character 1
3 Field_len Numeric 3 0
4 Field_dec Numeric 4 0
Used in application programs, COPY STRUCTURE EXTENDED permits you to create or modify the structure of a database file programmatically. To create a new database file from the structure extended file, use CREATE FROM. If you need an empty structure extended file, use CREATE.
Notes
■ Character field lengths greater than 255: In CA-Clipper, the
maximum character field length is 64K. For compatibility reasons, field lengths greater than 255 are represented as a combination of the Field_dec and Field_len fields. After COPYing STRUCTURE EXTENDED, you can use the following formula to determine the length of any character field:
■ This example creates Struc.dbf from Sales.dbf as a structure
extended file and then lists the contents of Struc.dbf to illustrate
the typical layout of field definitions:
USE Sales NEW
COPY STRUCTURE EXTENDED TO Struc
USE Struc NEW
LIST Field_name, Field_type, Field_len, Field_dec
Result:
1 BRANCH C 3 0
2 SALESMAN C 4 0
3 CUSTOMER C 4 0
4 PRODUCT C 25 0
5 AMOUNT N 8 2
6 NOTES C 0 125
// Field length is 32,000 characters
FIELDSidField list specifies the list of fields to copy to the target file. The default is all fields.
TOxcFile specifies the name of the target file. The file name can be specified either as a literal file name or as a character expression enclosed in parentheses. If SDF or DELIMITED is specified, .txt is the default extension. Otherwise, .dbf is the default extension.
scope defines the portion of the current database file to COPY. The default is ALL records.
WHILElCondition specifies the set of records meeting the condition from the current record until the condition fails.
FORlCondition specifies the conditional set of records to copy within the given scope.
SDF specifies the output file type as a System Data Format ASCII text file. Records and fields are fixed length.
DELIMITED specifies the output file type as a delimited ASCII text file where character fields are enclosed in double quotation marks (the default delimiter). Records and fields are variable length.
DELIMITED WITH BLANK identifies an ASCII text file in which fields are separated by one space and character fields have no delimiters.
DELIMITED WITHxcDelimiter identifies a delimited ASCII text file where character fields are enclosed using the specified delimiter. xcDelimiter can be specified either as a literal character or as a character expression enclosed in parentheses.
See the tables below for more information regarding the format specifications for ASCII text files created using these arguments.
VIA xcDriver specifies the replaceable database driver (RDD) to use to create the resulting copy. cDriver is name of the RDD specified as a character expression. If cDriver is specified as a literal value, it must be enclosed in quotes.
If the VIA clause is omitted, COPY TO uses the driver in the current work area. If you specify the VIA clause, you must REQUEST the appropriate RDDs to be linked into the application.
Note: If the DELIMITED WITH clause is specified on a COPY or APPEND command, it must be the last clause specified.
Description
COPY TO is a database command that copies all or part of the current database file to a new file. Records contained in the active database file are copied unless limited by a scope, a FOR|WHILE clause, or a filter.
If DELETED is OFF, deleted records in the source file are copied to xcFile where they retain their deleted status. If DELETED is ON, however, no deleted records are copied. Similarly, if a FILTER has been SET, invisible records are not copied.
Records are copied in controlling index order if there is an index open in the current work area and SET ORDER is not zero. Otherwise, records are copied in natural order.
In a network environment, CA-Clipper opens the target database file EXCLUSIVEly before the COPY TO operation begins. Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information.
This table shows the format specifications for SDF text files:
SDF Text File Format Specifications
File Element Format
Character fields Padded with trailing blanks
Date fields yyyymmdd
Logical fields T or F
Memo fields Ignored
Numeric fields Padded with leading blanks for zeros
Field separator None
Record separator Carriage return/linefeed
End of file marker 1A hex or Chr(26)
This table shows the format specifications for DELIMITED and DELIMITED WITHxcDelimiter ASCII text files:
DELIMITED Text File Format Specifications
File Element Format
Character fields Delimited, with trailing blanks truncated
Date fields yyyymmdd
Logical fields T or F
Memo fields Ignored
Numeric fields Leading zeros truncated
Field separator Comma
Record separator Carriage return/linefeed
End of file marker 1A hex or Chr(26)
This table shows the format specifications for DELIMITED WITH BLANK ASCII text files:
DELIMITED WITH BLANK Text File Format Specifications
File Element Format
Character fields Not delimited, trailing blanks truncated
Date fields yyyymmdd
Logical fields T or F
Memo fields Ignored
Numeric fields Leading zeros truncated
Field separator Single blank space
Record separator Carriage return/linefeed
End of file marker 1A hex or Chr(26)
Examples
■ This example demonstrates copying to another database file:
USE Sales NEW
COPY TO Temp
■ This example demonstrates the layout of a DELIMITED file:
COPY NEXT 1 TO Temp DELIMITED
TYPE Temp.txt
Result:
"Character",12.00,19890801,T
■ This example demonstrates the layout of an SDF file with four
fields, one for each data type:
USE Testdata NEW
COPY NEXT 1 TO Temp SDF
TYPE Temp.txt
Result:
Character 12.0019890801T
■ This example demonstrates the layout of a DELIMITED file WITH
a different delimiter:
COPY NEXT 1 TO Temp DELIMITED WITH '
TYPE Temp.txt
Result:
'Character',12.00,19890801,T
COUNT TO <idVar>
[<scope>] [WHILE <lCondition>] [FOR <lCondition>]
Arguments
TOidVar identifies the variable that holds the COUNT result. A variable that either does not exist or is invisible is created as a private variable whose scope is the current procedure.
scope is the portion of the current database file to COUNT. The default is ALL records.
WHILElCondition specifies the set of records meeting the condition from the current record until the condition fails.
FORlCondition specifies the conditional set of records to COUNT within the given scope.
Description
COUNT tallies the number of records from the current work area that match the specified record scope and conditions. The result is then placed in the specified variable. idVar can be a variable of any storage class including a field.
Examples
■ This example demonstrates a COUNT of Branches in Sales.dbf:
USE Sales NEW
COUNT TO nBranchCnt FOR Branch = 100
? nBranchCnt // Result: 4
■ This example tallies the number of records in Sales.dbf whose
Branch has the value of 100 and assigns the result to the Count field
in Branch.dbf for branch 100:
USE Branch INDEX Branch NEW
SEEK 100
USE Sales INDEX SalesBranch NEW
SEEK 100
COUNT TO Branch->Count WHILE Branch = 100
xcExtendedDatabase is the name of the empty structure extended database file. This argument can be specified either as a literal database file name or as a character expression enclosed in parentheses. If no extension is specified, .dbf is the default extension.
Description
CREATE produces an empty structure extended database file with the following structure:
Structure of an Extended File
Field Name Type Length Decimals
1 Field_name Character 10
2 Field_type Character 1
3 Field_len Numeric 3 0
4 Field_dec Numeric 4 0
Like COPY STRUCTURE EXTENDED, CREATE can be used in conjunction with CREATE FROM to form a new database file. Unlike COPY STRUCTURE EXTENDED, CREATE produces an empty database file and does not require the presence of another database file to create it.
xcExtendedDatabase is automatically opened in the current work area after it is created.
Examples
■ This example creates a new structure extended file, places the
definition of one field into it, and then CREATEs a new database file
FROM the extended structure:
CREATE TempStru
APPEND BLANK
REPLACE Field_name WITH "Name",;
Field_type WITH "C",;
Field_len WITH 25,;
Field_dec WITH 0
CLOSE
CREATE NewFile FROM TempStru
Create a new .dbf file from a structure extended file
Syntax
CREATE <xcDatabase> FROM <xcExtendedDatabase> [NEW]
[ALIAS <xcAlias>] [VIA <cDriver>]
Arguments
xcDatabase is the name of the new database file to create from the structure extended file.
xcExtendedDatabase is the name of a structure extended file to use as the structure definition for the new database file.
Both of these arguments can be specified either as literal database file names or as character expressions enclosed in parentheses. If an extension is not specified, the default is .dbf.
NEW opens xcDatabase in the next available work area making it the current work area. If this clause is not specified, xcDatabase is opened in the current work area.
ALIASxcAlias is the name to associate with the work area when xcDatabase is opened. You may specify the alias name as a literal name or as a character expression enclosed in parentheses. A valid xcAlias may be any legal identifier (i.e., it must begin with an alphabetic character and may contain numeric or alphabetic characters and the underscore). Within a single application, CA-Clipper will not accept duplicate aliases. If this clause is not specified, the alias defaults to the database file name.
VIA cDriver specifies the replaceable database driver (RDD) to use to process the current work area. cDriver is the name of the RDD specified as a character expression. If you specify cDriver as a literal value, you must enclose it in quotes.
Description
CREATE FROM produces a new database file with the field definitions taken from the contents of a structure extended file. To qualify as a structure extended file, a database file must contain the following four fields:
Structure of an Extended File
Field Name Type Length Decimals
1 Field_name Character 10
2 Field_type Character 1
3 Field_len Numeric 3 0
4 Field_dec Numeric 4 0
xcDatabase is automatically opened in the current work area after it is created.
Notes
■ Data dictionaries: For data dictionary applications, you can
have any number of other fields within the structure extended file to describe the extended field attributes. You may, for example, want to have fields to describe such field attributes as a description, key flag, label, color, picture, and a validation expression for the VALID clause. When you CREATE FROM, CA-Clipper creates the new database file from the required fields only, ignoring all other fields in the extended structure. Moreover, CA-Clipper is not sensitive to the order of the required fields.
■ Character field lengths greater than 255: There is one method
for creating a character field with a length greater than 255 digits:
- Specify the field length using both the Field_len and
Field_dec fields according to the following formulation:
■ This example is a procedure that simulates an interactive
CREATE utility:
CreateDatabase("NewFile")
RETURN
FUNCTION CreateDatabase( cNewDbf )
CREATE TmpExt // Create empty structure extended
USE TmpExt
lMore := .T.
DO WHILE lMore // Input new field definitions
APPEND BLANK
CLEAR
@ 5, 0 SAY "Name.....: " GET Field_name
@ 6, 0 SAY "Type.....: " GET Field_type
@ 7, 0 SAY "Length...: " GET Field_len
@ 8, 0 SAY "Decimals.: " GET Field_dec
READ
lMore := (!Empty(Field_name))
ENDDO
// Remove all blank records
DELETE ALL FOR Empty(Field_name)
PACK
CLOSE
// Create new database file
CREATE (cNewDbf) FROM TmpExt
ERASE TmpExt.dbf
RETURN NIL
■ This example creates a new definition in a structure extended
file for a character field with a length of 4000 characters:
APPEND BLANK
REPLACE Field_name WITH "Notes",;
Field_type WITH "C",;
Field_len WITH 4000 % 256,;
Field_dec WITH INT(4000 / 256)
cDate is a character string consisting of numbers representing the month, day, and year separated by any character other than a number. The month, day, and year digits must be specified in accordance with the SET DATE format. If the century digits are not specified, the century is determined by the rules of SET EPOCH.
Returns
CToD() returns a date value. If cDate is not a valid date, CToD() returns an empty date.
Description
CToD() is a character conversion function that converts a character string to a date. To initialize an empty date for date entry, specify cDate as a null string (""), Space(8), or " / / ".
CToD() is used whenever you need a literal date value. Some examples are:
■ Initializing a variable to a date value
■ Specifying a literal date string as an argument of a RANGE
clause of @...GET
■ Specifying a literal date string in order to perform date
arithmetic
■ Comparing the result of a date expression to a literal date
string
■ REPLACEing a date field with a literal date string
CToD() is the inverse of DToC() which converts a date value to a character string in the format specified by SET DATE and SET CENTURY. DToS() also converts a date value to a character string in the form yyyymmdd.
Examples
■ This example uses CToD() to initialize two date variables,
using one as a GET and the other for RANGE validation:
SET CENTURY ON
dBegin := CToD("01-26-1876")
dCurrent := CToD("")
@ 10, 10 SAY "Enter date:" GET dCurrent ;
RANGE dBegin, Date()
READ
■ This example uses CToD() to create a date value within a FOR
condition:
USE Inventory NEW
REPLACE ALL Inventory->Price WITH ;
Inventory->Price * 1.1 FOR ;
Inventory->InvDate < CToD("10/10/90")
cDrivespec specifies the letter of the disk drive to query. If not specified, the default is the current DOS drive.
Returns
CurDir() returns the current DOS directory of the drive specified by cDrivespec as a character string without either leading or trailing backslash () characters.
If an error occurs, or the current directory of the specified drive is the root directory, CurDir() returns a null string ("").
Description
CurDir() is an environment function that gives you the name of the current DOS directory, ignoring the SET DEFAULT and SET PATH settings.
Examples
■ These examples illustrate various CurDir() results:
? CurDir("E:") // Result: null string--root directory
? CurDir("C") // Result: CLIP53\SOURCE
? CurDir("C:") // Result: CLIP53\SOURCE
? CurDir() // Result: null string--root directory
? CurDir("A") // Result: null string--drive not ready
■ This example changes the current DOS directory to a new value
if it does not match a specified directory:
IF CurDir("C:") != "CLIP53\SOURCE"
RUN CD \CLIP53\SOURCE
ENDIF
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/EXAMPLEA.ASM
Append a new record to the database open in the current work area
Syntax
dbAppend([<lReleaseRecLocks>]) → NIL
Arguments
lReleaseRecLocks is a logical data type that if true (.T.), clears all pending record locks, then appends the next record. If lReleaseRecLocks is false (.F.), all pending record locks are maintained and the new record is added to the end of the Lock List. The default value of lReleaseRecLocks is true (.T.).
Returns
dbAppend() always returns NIL.
Description
dbAppend() is a database function that lets you add records to the current database. The enhancement to this function lets you maintain multiple record locks during an append.
dbAppend() without a parameter as in earlier versions of CA-Clipper, clears all pending record locks prior to an append. This is the same as dbAppend(.T.).
Examples
■ This example appends a blank record to the database, Sales,
without releasing the record locks in the current Lock List, and then
checks for a network error:
USE Sales NEW
SET INDEX TO Sales
dbAppend(.F.)
IF NetErr()
? "A network error has occurred!"
ENDIF
dbClearFilter() clears the logical filter condition, if any, for the current work area.
dbClearFilter() performs the same function as the standard SET FILTER command with no expression specified. For more information, refer to the SET FILTER command.
Notes
■ Logical records: dbClearFilter() affects the logical
visibility of records in the current work area. For more information, refer to dbSetFilter() and the SET FILTER command.
Examples
■ The following example sets a filter, lists data as filtered,
and then clears the filter:
USE Employee NEW
dbSetFilter( {|| Age < 40}, "Age < 40" )
LIST Employee->Name
dbClearFilter()
dbClearIndex() closes any active indexes for the current work area. Any pending index updates are written and the index files are closed.
dbClearIndex() performs the same function as the standard SET INDEX command with no indexes specified. For more information, refer to the SET INDEX command.
Examples
■ The following example clears index files if any are set:
cFirst := "Winston"
dbUseArea( .T., "DBFNTX", "Sales", "Sales", .T. )
dbSetIndex( "FIRSTNAM" )
dbSetIndex( "LASTNAME" )
//
IF IndexOrd() > 0 // is there an index?
dbClearIndex() // clear index files
ELSE
COPY TO FILE TEMP SDF // copy to SDF in natural
ENDIF // order
dbClearRelation() clears any active relations for the current work area.
dbClearRelation() performs the same function as the standard SET RELATION TO command with no clauses specified. For more information, refer to the SET RELATION command.
Examples
■ The following example sets a relation, lists data, and then
clears the relation:
USE Employee NEW
USE Department NEW INDEX Dept
//
SELECT Employee
dbSetRelation("Department", ;
{|| Employee->Dept}, "Employee->Dept")
LIST Employee->Name, Department->Name
dbClearRelation()
dbCloseAll() releases all occupied work areas from use. It is equivalent to calling dbCloseArea() on every occupied work area. dbCloseAll() has the same effect as the standard CLOSE DATABASES command. For more information, refer to the USE and CLOSE commands.
Examples
■ The following example closes all work areas:
cLast := "Winston"
dbUseArea( .T., "DBFNTX", "Sales", "Sales", .T. )
dbSetIndex( "SALEFNAM" )
dbSetIndex( "SALELNAM" )
//
dbUseArea( .T., "DBFNTX", "Colls", "Colls", .T. )
dbSetIndex( "COLLFNAM" )
dbSetIndex( "COLLLNAM" )
//
dbSelectArea( "Sales" ) // select "Sales" work area
//
IF ( Sales->(dbSeek(cLast)) )
IF Sales->( Deleted() )
IF RLock()
Sales->( dbRecall() )
? "Record deleted: ", Sales( Deleted() )
ENDIF
ENDIF
ELSE
? "Not found"
ENDIF
dbCloseAll() // close all work areas
dbCloseArea() releases the current work area from use. Pending updates are written, pending locks are released, and any resources associated with the work area are closed or released. dbCloseArea() is equivalent to the standard CLOSE command or the USE command with no clauses. For more information, refer to the USE and CLOSE commands.
Examples
■ The following example closes a work area via an alias
reference:
cLast := "Winston"
//
dbUseArea( .T., "DBFNTX", "Sales", "Sales", .T. )
dbSetIndex( "SALEFNAM" )
dbSetIndex( "SALELNAM" )
//
dbUseArea( .T., "DBFNTX", "Colls", "Colls", .T. )
dbSetIndex( "COLLFNAM" )
dbSetIndex( "COLLLNAM" )
//
dbSelectArea( "Sales" ) // select "Sales" work area
//
IF ( Sales->(dbSeek(cLast)) )
IF Sales->( Deleted() ) .AND. Sales->( RLock() )
Sales->( dbRecall() )
? "Record deleted: ", Sales( Deleted() )
ENDIF
ELSE
? "Not found"
Colls->( dbCloseArea() )
ENDIF
dbCommit() causes all updates to the current work area to be written to disk. All updated database and index buffers are written to DOS and a DOS COMMIT request is issued for the database (.dbf) file and any index files associated with the work area.
dbCommit() performs the same function as the standard COMMIT command except that it operates only on the current work area. For more information, refer to the COMMIT command.
Notes
■ Network environment: dbCommit() makes database updates visible
to other processes. To insure data integrity, issue dbCommit() before an UNLOCK operation. For more information, refer to the "Network Programming" chapter in the Programming and Utilities Guide.
■ dbCommit() uses DOS interrupt 21h function 68h to perform the
solid-disk write. It is up to the network operating system to properly implement this request. Check with the network vendor to see if this is supported.
Examples
■ In this example, COMMIT is used to force a write to disk after
a series of memory variables are assigned to field variables:
USE Sales EXCLUSIVE NEW
MEMVAR->Name := Sales->Name
MEMVAR->Amount := Sales->Amount
//
@ 10, 10 GET MEMVAR->Name
@ 11, 10 GET MEMVAR->Amount
READ
//
IF Updated()
APPEND BLANK
REPLACE Sales->Name WITH MEMVAR->Name
REPLACE Sales->Amount WITH MEMVAR->Amount
Sales->( dbCommit() )
ENDIF
dbCommitAll() causes all pending updates to all work areas to be written to disk. It is equivalent to calling dbCommit() for every occupied work area.
For more information, refer to dbCommit() and the COMMIT command.
Notes
■ dbCommitAll() uses DOS interrupt 21h function 68h to perform
the solid-disk write. It is up to the network operating system to properly implement this request. Check with the network vendor to see if this is supported.
Examples
■ The following example writes all pending updates to disk:
cLast := "Winston"
//
dbUseArea( .T., "DBFNTX", "Sales", "Sales", .T. )
dbSetIndex( "SALEFNAM" )
dbSetIndex( "SALELNAM" )
//
dbUseArea( .T., "DBFNTX", "Colls", "Colls", .T. )
dbSetIndex( "COLLFNAM" )
dbSetIndex( "COLLLNAM" )
dbSelectArea( "Sales" ) // select "Sales" work area
IF ( Sales->(dbSeek(cLast)) )
IF Sales->( Deleted() ) .AND. Sales( RLock() )
Sales->( dbRecall() )
? "Deleted record has been recalled."
ENDIF
ELSE
? "Not found"
ENDIF
//
// processing done, write updates to disk and close
dbCommitAll()
dbCloseAll()
QUIT
cDatabase is the name of the new database file, with an optional drive and directory, specified as a character string. If specified without an extension, .dbf is assumed.
aStruct is an array that contains the structure of cDatabase as a series of subarrays, one per field. Each subarray contains the definition of each field's attributes and has the following structure:
Field Definition Subarray
Position Metasymbol Dbstruct.ch
1 cName DBS_NAME
2 cType DBS_TYPE
3 nLength DBS_LEN
4 nDecimals DBS_DEC
cDriver specifies the replaceable database driver (RDD) to use to process the current work area. cDriver is the name of the RDD specified as a character expression. If you specify cDriver as a literal value, you must enclose it in quotes.
Returns
dbCreate() always returns NIL.
Description
dbCreate() is a database function that creates a database file from an array containing the structure of the file. You may create the array programmatically or by using dbStruct(). dbCreate() is similar to the CREATE FROM command which creates a new database file structure from a structure extended file. Use CREATE or COPY STRUCTURE EXTENDED commands to create a structure extended file.
Before using dbCreate(), you must first create the aStruct array and fill it with the field definition arrays according to the structure in Field Definition Subarray table (above). There are some specific rules for creating a field definition array, including:
■ Specify all field attributes with a value of the proper data
type for the attribute. The decimals attribute must be specified— even for non-numeric fields. If the field does not have a decimals attribute, specify zero.
■ Specify the type attribute using the first letter of the data
type as a minimum. Use longer and more descriptive terms for readability. For example, both "C" and "Character" can be specified as the type attribute for character fields.
■ In CA-Clipper, character fields contain up to 64,000
characters. Unlike the CREATE FROM command, dbCreate() does not use the decimals attribute to specify the high-order part of the field length. Specify the field length directly, regardless of its magnitude.
To make references to the various elements of the field definition subarray more readable, the header file called dbstruct.ch is supplied. It contains the #defines to assign a name to the array position for each field attribute. It is located in \CLIP53\INCLUDE.
Notes
■ Duplicate field names: dbCreate() does not check for duplicate
field names. Therefore, be careful not to use the same field name twice.
■ EG_ARG error: dbCreate() generates an EG_ARG error if the
filename is NIL.
Examples
■ This example creates an empty array and then adds field
definition subarrays using the AAdd() function before creating
People.dbf. You might use this technique to add field definitions to
your structure array dynamically:
aDbf := {}
AAdd(aDbf, { "Name", "C", 25, 0 })
AAdd(aDbf, { "Address", "C", 1024, 0 })
AAdd(aDbf, { "Phone", "N", 13, 0 })
//
dbCreate("People", aDbf)
■ This example performs the same types of actions but declares
the structure array as a two-dimensional array, and then uses
subscript addressing to specify the field definitions. It will be
created using the DBFMDX RDD:
#include "Dbstruct.ch"
//
LOCAL aDbf[1][4]
aDbf[1][ DBS_NAME ] := "Name"
aDbf[1][ DBS_TYPE ] := "Character"
aDbf[1][ DBS_LEN ] := 25
aDbf[1][ DBS_DEC ] := 0
//
dbCreate("Name", aDbf, "DBFMDX")
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, header file is dbstruct.ch.
cIndexName is a character value that specifies the file name of the index file to be created.
cKeyExpr is a character value that expresses the index key expression in textual form.
bKeyExpr is a code block that expresses the index key expression in executable form.
lUnique is an optional logical value that specifies whether a unique index is to be created. If lUnique is omitted, the current global _SET_UNIQUE setting is used.
Returns
dbCreateIndex() always returns NIL.
Description
dbCreateIndex() creates an index for the database (.dbf) file associated with the current work area. If the work area has active indexes, they are closed. After the new index is created, it becomes the controlling index for the work area and is positioned to the first logical record.
dbCreateIndex() performs the same function as the standard INDEX command. For more information, refer to the INDEX command.
Notes
■ Side effects: dbCreateIndex() is guaranteed to create an index
that, when made active, will impose the specified logical order on the database. The key expression is not necessarily evaluated at any particular time, by any particular means, or on any particular record or series of records. If the key expression relies on information external to the database file or work area, the effect is unpredictable. If the key expression changes the state of the work area (e.g., by moving to a different record or changing the contents of a record), the effect is unpredictable.
■ Evaluation context: When the key expression is evaluated, the
associated work area is automatically selected as the current work area before the evaluation; the previously selected work area is automatically restored afterward.
■ Network environment: dbCreateIndex() creates the new index for
the exclusive use of the current process.
■ Illegal expression: If cKeyExpr evaluates to an illegal
expression, the code block will always evaluate to end-of-file (EOF).
Examples
■ This example creates an index file, Name, indexed on the Name
field:
USE Employees NEW
dbCreateIndex( "Name", "Name", { || Name })
dbDelete() marks the current record as deleted. Records marked for deletion can be filtered using SET DELETED or removed from the file using the PACK command.
dbDelete() performs the same function as the standard DELETE command with a scope of the current record. For more information, refer to the DELETE command.
Notes
■ Logical records: If the global _SET_DELETED status is true
(.T.), deleted records are not logically visible. That is, database operations which operate on logical records will not consider records marked for deletion. Note, however, that if _SET_DELETED is true (.T.) when the current record is marked for deletion, the record remains visible until it is no longer the current record.
■ Network environment: For a shared database on a network,
dbDelete() requires the current record to be locked. For more information, refer to the "Network Programming" chapter of the Programming and Utilities Guide.
Examples
■ The following example deletes a record after a successful
record lock:
cLast := "Winston"
dbUseArea( .T., "DBFNTX", "Sales", "Sales", .T. )
dbSetIndex( "LASTNAME" )
//
IF ( Sales->(dbSeek(cLast)) )
IF Sales->( RLock() )
Sales->( dbDelete() )
? "Record deleted: ", Sales->( Deleted() )
ELSE
? "Unable to lock record..."
ENDIF
ELSE
? "Not found"
ENDIF
nTop, nLeft, nBottom, and nRight define the upper-left and lower-right coordinates of the dbEdit() window. Row values can range from zero to MaxRow() and column positions can range from zero to MaxCol(). If not specified, the default coordinates are 0, 0, MaxRow(), and MaxCol().
acColumns is an array of character expressions containing database field names or expressions to use as column values for each row displayed. If this argument is not specified, dbEdit() displays all fields in the current work area as columns.
cUserFunction is the name of a user-defined function that executes when an unrecognizable key is pressed or there are no keys pending in the keyboard buffer. Specify the function name as a character expression without parentheses or arguments. Note that the behavior of dbEdit() is affected by the presence of this argument. Refer to the discussion below for more information.
acColumnSayPictures is a parallel array of picture clauses to format each column. Specifying cColumnSayPicture instead of an array displays all columns with the same format. Refer to Transform() or @...SAY for more information on pictures.
acColumnHeaders is a parallel array of character expressions that define the headings for each column. Specifying cColumnHeader gives the same heading for all columns. To display a multi-line heading, embed a semicolon in the heading expression where you want the string to break. If not specified, column headings are taken from the acColumns array or the field names in the current work area, if the acColumns argument is not specified.
acHeadingSeparators is a parallel array of character expressions that define the characters used to draw horizontal lines separating column headings from the field display area. Specifying cHeadingSeparator instead of an array uses the same heading separator for all columns. If this argument is not specified, the default separator is a double graphics line.
acColumnSeparators is a parallel array of character expressions that define the characters used to draw vertical lines separating the columns. Specifying cColumnSeparator instead of an array uses the same separator for all columns. If this argument is not specified, the default separator is a single graphics line.
acFootingSeparators is a parallel array of character expressions that define the characters used to draw horizontal lines separating column footings from the field display area. Specifying cFootingSeparator instead of an array uses the same footing separator for all columns. If this argument is not specified, there is no footing separator.
acColumnFootings is a parallel array of character expressions that define footings for each column. Specifying cColumnFooting instead of an array gives the same footing for all columns. To display a multi- line footing, embed a semicolon in the footing expression where you want the string to break. If this argument is not specified, there are no column footings.
Returns
dbEdit() always returns NIL.
Description
dbEdit() is a user interface and compatibility function that displays records from one or more work areas in a table form. The dbEdit() window display is a grid of cells divided into columns and rows. Columns correspond to database fields and rows correspond to database records. Each column is defined by an element of the acColumns array. The display width of each column is determined by the evaluation of the column expression in acColumns array or the column picture specified in the acColumnSayPictures array.
All cursor movement keys are handled within dbEdit(), including Page up, Page down, Home, End, the four arrow keys, and all Ctrl key combinations that produce cursor movement. The navigation keys that dbEdit() responds to when a user function argument is not specified are listed in the Active Keys table below:
dbEdit() Active Keys
Key Action
Up arrow Up one row
Down arrow Down one row
Left arrow Column left
Right arrow Column right
Ctrl+Left arrow Pan left one column
Ctrl+Right arrow Pan right one column
Home Leftmost current screen column
End Rightmost current screen column
Ctrl+Home Leftmost column
Ctrl+End Rightmost column
PgUp Previous screen
PgDn Next screen
Ctrl+PgUp First row of current column
Ctrl+PgDn Last row of current column
Return Terminate dbEdit()
Esc Terminate dbEdit()
When the user function argument (cUserFunction) is specified, all keys indicated in the Active Keys table are active with the exception of Esc and Return. When dbEdit() calls the user function, it automatically passes two arguments:
■ The current mode passed as a numeric value
■ The index of the current column in acColumns passed as a
numeric value
The mode parameter indicates the current state of dbEdit() depending on the last key executed. The possible mode values are listed in the dbEdit() Modes table below:
dbEdit() Modes
Status Dbedit.ch Description
0 DE_IDLE Idle, any cursor movement keystrokes have been
handled and no keystrokes are pending
1 DE_HITTOP Attempt to cursor past top of file
2 DE_HITBOTTOM Attempt to cursor past bottom of file
3 DE_EMPTY No records in work area
4 DE_EXCEPT Key exception
The index parameter points to the position of the current column definition in the acColumns array. If acColumns is not specified, the index parameter points to the position of the field in the current database structure. Access the field name using Field().
A user-defined function must return a value that indicates to dbEdit() the action to perform. The User Function Return Values table below lists the possible return values and the corresponding actions:
dbEdit() User Function Return Values
Value Dbedit.ch Description
0 DE_ABORT Abort dbEdit()
1 DE_CONT Continue dbEdit()
2 DE_REFRESH Force reread/repaint and continue; after repaint,
process keys and go to idle
A number of instances affect calls to the user function:
■ A key exception occurs. This happens when dbEdit() fetches a
keystroke that it does not recognize from the keyboard. Any pending keys remain in the keyboard buffer until fetched within the user function or until dbEdit() continues.
■ dbEdit() enters the idle mode (i.e., all pending keys have
been processed). This happens when the keyboard is empty or after a screen refresh. In this instance, there is one call to the user function and then dbEdit() waits for a key.
■ Beginning or end of file is encountered. This is the same as
idle. All executable keys are performed, and there is one call to the user function with the appropriate status message.
Note that when dbEdit() is first executed, all keys pending in the keyboard buffer are executed and then dbEdit() enters the idle mode with a user function call. If no keys are pending, the idle mode is immediate.
The user function should handle all modes and status messages received from dbEdit().
A user-defined function must ensure that the dbEdit() status is equivalent to DE_EXCEPT (4); otherwise, the value of LastKey() is meaningless and a Return value of DE_REFRESH (2) will place the application into an endless loop. For example:
dbEdit() is fully re-entrant, which means you can make nested calls to it. Using this feature, you can have multiple browse windows on the screen at the same time.
dbEdit() is a compatibility function and, therefore, no longer recommended as a programmable browse facility. As such, it is superseded by the TBrowse object class. For more information, refer to TBrowse class in this chapter.
Examples
■ This example demonstrates a generic call to dbEdit():
USE Names NEW
dbEdit()
■ This example demonstrates calling dbEdit() with a user
function:
#include "dbedit.ch"
#include "inkey.ch"
// Array must be visible to other user-defined programs in
// program
STATIC acColumns := {}
PROCEDURE Main()
USE Names NEW
INDEX ON Names->Lastname + Names->FirstName TO Names
CLS
acColumns := { "LastName", "FirstName" }
dbEdit( 5, 5, 20, 70, acColumns, "UserFunc" )
RETURN
FUNCTION UserFunc( nMode, nCol )
LOCAL nKey := LastKey()
LOCAL nRetVal := DE_CONT // Default return value
DO CASE
CASE nMode == DE_IDLE
nRetVal := IdleFunc()
CASE nMode == DE_HITTOP
Tone( 100, 3 )
CASE nMode == DE_HITBOTTOM
Tone( 100, 3 )
nRetVal := AppendFunc( nKey )
CASE nMode == DE_EMPTY
nRetVal := EmptyFunc()
CASE nMode == DE_EXCEPT
nRetVal := ExceptFunc( nKey, nCol )
OTHERWISE
Tone( 100, 3 )
ENDCASE
RETURN nRetVal
FUNCTION AppendFunc( nKey )
LOCAL nRetVal := DE_CONT // Default return value
IF nKey == K_DOWN // If DOWN ARROW
APPEND BLANK // Append blank record
// Note: The appended record will appear at the top of the
// dbEdit() screen when the database file is indexed.
nRetVal := DE_REFRESH // Refresh screen
ENDIF
RETURN nRetVal
FUNCTION ExceptFunc( nKey, nCol )
LOCAL nRetVal := DE_CONT // Default return value
DO CASE
CASE nKey == K_ESC // If ESCAPE
nRetVal := DE_ABORT // Exit
CASE nKey == K_RETURN // If RETURN
nRetVal := EditFunc( nCol ) // Function to edit
// field
// Toggle DELETED status
CASE nKey == K_DEL .AND. LastRec() != 0 // DELETE pressed
IF Deleted()
RECALL
ELSE
DELETE
ENDIF
OTHERWISE
Tone( 100, 1 )
ENDCASE
RETURN nRetVal
FUNCTION EditFunc( nCol )
LOCAL cIndexVal // Value of current key expression
LOCAL nRetVal // Return value
LOCAL nField // Position of current field
LOCAL cFieldVal // Value of current field
LOCAL nCursSave // Preserve state of cursor
// This will return an error if no index is open
cIndexVal := &( IndexKey(0) )
nField := FieldPos( acColumns[nCol] )
IF nField != 0
nCursSave := SetCursor() // Save state of cursor
SetCursor(1) // Change cursor shape
cFieldVal := FieldGet( nField ) // Save contents
// of field
@ Row(), Col() GET cFieldVal // GET new value
READ
FieldPut( nField, cFieldVal ) // REPLACE with
// new value
SetCursor( nCursSave ) // Restore cursor
// shape
ENDIF
IF cIndexVal != &( IndexKey(0) ) // If key expression
// changed
nRequest := DE_REFRESH // Refresh screen
ELSE // Otherwise
nRequest := DE_CONT // Continue
ENDIF
RETURN nRequest
FUNCTION IdleFunc()
// Idle routine
RETURN DE_CONT
FUNCTION EmptyFunc()
// Empty Records routine
RETURN DE_CONT
bBlock is a code block to execute for each record processed.
bForCondition is an optional condition specified as a code block that is evaluated for each record in the scope. It provides the same functionality as the FOR clause of record processing commands.
bWhileCondition is an optional condition specified as a code block that is evaluated for each record from the current record until the condition returns false (.F.). It provides the same functionality as the WHILE clause of record processing commands.
nNextRecords is an optional number that specifies the number of records to process starting with the current record. It is the same as the NEXT clause.
nRecord is an optional record number to process. If this argument is specified, bBlock will be evaluated for the specified record. This argument is the same as the RECORD clause.
lRest is an optional logical value that determines whether the scope of dbEval() is all records, or, starting with the current record, all records to the end of file. This argument corresponds to the REST and ALL clauses of record processing commands. If true (.T.) , the scope is REST; otherwise, the scope is ALL records. If lRest is not specified the scope defaults to ALL.
Returns
dbEval() always returns NIL.
Description
dbEval() is a database function that evaluates a single block for each record within the current work area that matches a specified scope and/or condition. On each iteration, dbEval() evaluates the specified block. All records within the scope or matching the condition are processed until the end of file is reached.
By default, dbEval() operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression.
dbEval() is similar to AEval() which applies a block to each element in an array. Like AEval(), dbEval() can be used as a primitive for the construction of user-defined commands that process database files. In fact, many of the standard CA-Clipper database processing commands are created using dbEval().
Refer to the Code Blocks section in the "Basic Concepts" chapter of the Programming and Utilities Guide for more information on the syntax and theory of code blocks; and refer also to the Database System section in the same chapter for information on record scoping and conditions. Also refer to the CA-Clipper standard header file, std.ch, found in \CLIP53\INCLUDE for examples of CA-Clipper database command definitions that use dbEval().
Examples
■ This example uses dbEval() to implement Count(), a user-
defined function that counts the number of records in a work area
matching a specified scope. The scope is passed as an array to
Count(). To make the example more interesting, there is a user-
defined command to create the scope array, thereby allowing you to
specify the scope in a familiar form. Additionally, there is a set
of manifest constants that define the attributes of the scope object.
// Scope command definition
#command CREATE SCOPE <aScope> [FOR <for>] ;
[WHILE <while>] [NEXT <next>] [RECORD <rec>] ;
[<rest:REST>] [ALL];
=>;
<aScope> := { <{for}>, <{while}>, <next>, ;
<rec>, <.rest.> }
//
// Scope attribute constants
#define FOR_COND 1
#define WHILE_COND 2
#define NEXT_SCOPE 3
#define REC_SCOPE 4
#define REST_SCOPE 5
//
// Create a scope and count records using it
LOCAL mySet, myCount
USE Customer NEW
CREATE SCOPE mySet FOR Customer = "Smith" WHILE ;
Zip > "90000"
myCount := Count( mySet )
RETURN
FUNCTION Count( aScope )
LOCAL nCount := 0
dbEval( {|| nCount++},;
aScope[ FOR_COND ],;
aScope[ WHILE_COND ],;
aScope[ NEXT_SCOPE ],;
aScope[ REC_SCOPE ],;
aScope[ REST_SCOPE ];
)
RETURN nCount
nInfoType determines the type of information as specified by the constants below. Note, however, that not all constants are supported for all RDDs, nor are all constants supported by all field types. These constants are defined in the dbstruct.ch header file, which must be included (#include) in your application.
Field Information Type Constants
Constant Description
DBS_BLOB_LEN Returns the storage length of the data in a BLOB
(memo) file.
DBS_BLOB_OFFSET Returns the file offset of the data in a BLOB (memo)
file.
DBS_BLOB_POINTER Returns a numeric pointer to the data in a blob
file. This pointer can be used with BLOBDirectGet(),
BLOBDirectImport(), etc.
DBS_BLOB_TYPE Returns the data type of a BLOB (memo) field. This
is more efficient than using Type() or ValType()
since the data itself does not have to be retrieved
from the BLOB file in order to determine the type.
DBS_DEC Number of decimal places for the field.
DBS_LEN Length of the field.
DBS_NAME Name of the field.
DBS_TYPE Data type of the field.
nFieldPos is the position of the field in the database file structure.
expNewSetting is reserved for CA-Clipper future use. It can be omitted or specified as NIL.
Returns
dbFieldInfo() returns the current setting.
Description
dbFieldInfo() retrieves information about the state of a field. By default, this function operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
The field information that is available is defined by the RDD.
To support RDDs for other database models (such as dictionary-based databases) that store more information about each field or column, the CA-Clipper 5.3 RDD API has been enhanced. The dbFieldInfo() is designed to allow for additional nInfoType values that can be defined by third- party RDD developers.
Examples
■ The following example uses dbFieldInfo() to retrieve field
information:
#include dbstruct.ch
QOut(dbFieldInfo(DBS_NAME, 1)) // Same as FieldName(1)
FUNCTION DBOUTSTRUCT()
LOCAL aStruct := {}
LOCAL nFcount, i
nFcount := FCount()
FOR i := 1 TO nFcount
AAdd(aStruct, {FieldName(i), ;
dbFieldInfo(DBS_TYPE, i), ;
dbFieldInfo(DBS_LEN, i), ;
dbFieldInfo(DBS_DEC, i)})
NEXT
RETURN aStruct
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, header file is dbstruct.ch.
nFieldPos is the position of the field in the database file structure.
cTargetFile is the name of the file where the field data will be written, including an optional drive, directory and extension. See SetDefault() and SetPath() for file searching and creation rules. No default extension is assumed.
If cTargetFile does not exist, it is created. If it exists, this function attempts to open the file in exclusive mode and if successful, the file is written to without warning or error. If access is denied because, for example, another proess is using the file, NetErr() is set to TRUE.
nMode is a constant defining the copy mode, as shown in the table below:
dbFileGet() Constants
Constant Description
FILEGET_APPEND Appends to the file.
FILEGET_OVERWRITE Overwrites the file. This is the default.
Returns
dbFileGet() returns true (.T.) if successful; otherwise it returns false (.F.).
Description
dbFileGet() provides a mechanism for copying the contents of a field into a file. By default, this function operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
dbFileGet() is used in conjunction with dbFilePut() to transfer data back and forth between files and database fields.
Examples
■ This example exports the contents of a field that stores a
picture to a .GIF file, so that the file can be programmatically
displayed:
FUNCTION ShowPix()
LOCAL cPixFile := "picture.gif"
LOCAL nPos
// Customer database with a picture of each
// customer stored in a field called "Pix"
USE customer NEW VIA "DBFCDX"
nPos := FieldPos("Pix")
// Export the file's data for the current Pix field
IF ! dbFileGet(nPos, cPixFile, FILEGET_OVERWRITE )
Alert("Export of picture " + cPixFile +
" failed!")
ELSE
// Code for displaying picture would go here
ENDIF
nFieldPos is the position of the field in the database file structure.
cSourceFile is the name of the file containing the data to insert into the specified field, including an optional drive, directory and extension. See SetDefault() and SetPath() for file searching rules. No default extension is assumed.
This function attempts to open cSourceFile in shared mode. If the file does not exist, a runtime error is raised. If the file is successfully opened, the operation proceeds. If access is denied because, for example, another process has exclusive use of the file, NetErr() is set to true (.T.).
Note: There are no restrictions on the size of cSourceFile except that you must have enough disk space to make the copy.
Returns
dbFilePut() returns true (.T.) if successful; otherwise, it returns false (.F.).
Description
dbFilePut() provides a mechanism for copying the contents of a file into a field. By default, this function operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
dbFilePut() is used in conjunction with dbFileGet() to transfer data back and forth between files and database fields. You can use dbFilePut() with a variety of field types, including graphics images, word processor files, and printer fonts. These two functions are excellent for creating databases of documents, graphics, sounds, etc.
Note: DBFieldInfo ( DBS_BLOB_TYPE, nFieldPos ) will return "C" (string) for any memo field created using dbFilePut().
Examples
■ This example imports information from a word processing
document into a field, then uses BLOBGet() to extract the first 25
characters of the field:
FUNCTION Populate()
USE customer NEW VIA "DBFCDX"
DO WHILE .NOT. Eof()
GetPix( "Pix", SubStr(LastName, 1, 4) + CustID)
Customer->dbSkip()
ENDDO
FUNCTION GetPix(cPixField, cPixFile)
LOCAL nPos
nPos := FieldPos(cPixField)
// Import the picture field into the indicated field
IF ! dbFilePut(nPos, cPixFile)
Alert("Import of picture " + cPixFile + ;
" failed!")
ENDIF
Return the current filter expression as a character string
Syntax
dbFilter() → cFilter
Returns
dbFilter() returns the filter condition defined in the current work area as a character string. If no FILTER has been SET, dbFilter() returns a null string ("").
Description
dbFilter() is a database function used to save and re-execute an active filter by returning the filter expression as a character string that can be later recompiled and executed using the macro operator (&). This function operates like the dbRelation() and dbRSelect() functions which save and re-execute the linking expression of a relation within a work area.
Since each work area can have an active filter, dbFilter() can return the filter expression of any work area. This is done by referring to dbFilter() within an aliased expression as demonstrated below.
Notes
■ Declared variables: A character string returned by dbFilter()
may not operate correctly when recompiled and executed using the macro operator (&) if the original filter expression contained references to local or static variables, or otherwise depended on compile-time declarations.
Examples
■ This example opens two database files, sets two filters, and
then displays the filter expressions for both work areas:
USE Customer INDEX Customer NEW
SET FILTER TO Last = "Smith"
USE Invoices INDEX Invoices NEW
SET FILTER TO CustId = "Smi001"
SELECT Customer
//
? dbFilter() // Result: Last = "Smith"
? Invoices->(dbFilter()) // Result: Custid = "Smi001"
■ This user-defined function, CreateQry(), uses dbFilter() to
create a memory file containing the current filter expression in the
private variable cFilter:
FUNCTION CreateQry( cQryName )
PRIVATE cFilter := dbFilter()
SAVE ALL LIKE cFilter TO (cQryName + ".qwy")
RETURN NIL
■ You can later RESTORE a query file with this user-defined
function, SetFilter():
FUNCTION SetFilter()
PARAMETER cQryName
RESTORE FROM &cQryName..qwy ADDITIVE
SET FILTER TO &cFilter.
RETURN NIL
dbGoBottom() moves to the last logical record in the current work area.
dbGoBottom() performs the same function as the standard GO BOTTOM command. For more information, refer to the GO command.
Notes
■ Logical records: dbGoBottom() operates on logical records. If
there is an active index, dbGoBottom() moves to the last record in indexed order. If a filter is set, only records which meet the filter condition are considered.
■ Controlling order: If more than one index is active in the
work area, the operation is performed using the controlling order as set by dbSetOrder() or the SET ORDER command. For more information, refer to the SET ORDER command.
■ Network environment: For a shared file on a network, moving to
a different record may cause updates to the current record to become visible to other processes. For more information, refer to the "Network Programming" chapter in the Programming and Utilities Guide. This function will not affect the locked status of any record.
Examples
■ The following example uses dbGoBottom() to position the record
pointer on the last logical record:
cLast := "Winston"
dbUseArea( .T., "DBFNTX", "Sales", "Sales", .T. )
dbSetIndex( "LASTNAME" )
//
Sales->( dbGoBottom() )
IF ( Sales->Last == "Winston" )
IF RLock()
Sales->( dbDelete() )
? "Record deleted: ", Sales->( Deleted() )
ELSE
? "Unable to lock record..."
ENDIF
END
xIdentity is a unique value guaranteed by the structure of the data file to reference a specific item in a data source (database). In a Xbase data structure (.dbf) xIdentity is the record number. In other data formats, xIdentity is the unique primary key value. xIdentity could be an array offset or virtual memory handle if the data set is in memory instead of on disk.
Returns
dbGoto() always returns NIL.
Description
dbGoto() is a database function that positions the record pointer in the current work area at the specified xIdentity. In an Xbase data structure, this identity is the record number because every record, even an empty record, has a record number. In non-Xbase data structures, identity may be defined as something other than record number.
Examples
■ This example saves the current record number, searches for a
key, and then restores the record pointer to the saved position:
FUNCTION KeyExists( xKeyExpr )
LOCAL nSavRecord := RecNo() // Save the current record
// pointer position
LOCAL lFound
SEEK xKeyExpr
IF ( lFound := Found() )
.
.< statements >
.
ENDIF
dbGoto( nSavRecord ) // Restore the record
// pointer position
RETURN ( lFound )
dbGoTop() moves to the first logical record in the current work area.
dbGoTop() performs the same function as the standard GO TOP command. For more information, refer to the GO TOP command.
Notes
■ Logical records: dbGoTop() operates on logical records. If
there is an active index, dbGoTop() moves to the first record in indexed order. If a filter is set, only records which meet the filter condition are considered.
■ Controlling order: If more than one index is active in the
work area, the operation is performed using the controlling order as set by dbSetOrder() or the SET ORDER command. For more information, refer to the SET ORDER command.
■ Network environment: For a shared file on a network, moving to
a different record may cause updates to the current record to become visible to other processes. For more information, refer to the "Network Programming" chapter in the Programming and Utilities Guide. This function will not affect the locked status of any record.
Examples
■ This example demonstrates the typical use of dbGoTop():
dbGoTop()
WHILE ( !Eof() )
? FIELD->Name
dbSkip()
END
nInfoType determines the type of information, as specified by the constants below. Note, however, that not all constants are supported for all RDDs. These constants are defined in the dbinfo.ch header file, which must be included (#include) in your application.
File Information Type Constants
Constant Description
DBI_ALIAS Alias name of the work area as a string.
DBI_BLOB_DIRECT_LEN Returns the storage length of a data item in a
BLOB file. <expNewSetting> must specify a
valid BLOB pointer obtained from
dbFieldInfo(DBS_BLOB_POINTER, <nFieldpos>),
BLOBDirectPut() or BLOBDirectImport().
DBI_BLOB_DIRECT_TYPE Returns the data type of a data item in a BLOB
file. <expNewSetting> must specify a valid BLOB
pointer obtained from
DbFieldInfo (DBS_BLOB_POINTER, <nFieldpos>),
BLOBDirectPut(), or BLOBDirectImport().
DBI_BLOB_INTEGRITY Tests a BLOB file for the integrity of its
internal tables and returns a logical value
indicating the success, true (.T.) or failure,
false (.F.) of the integrity check. If the
integrity check fails, you can run
dbInfo(DBI_BLOB_RECOVER) which will
automatically correct the BLOB file's tables.
Checking a BLOB file's integrity is a disk
intensive operation and should only be
performed when the file's integrity is in
question.
DBI_BLOB_OFFSET Returns the file offset of a data item in a
BLOB file. <expNewSetting> must specify a valid
BLOB pointer obtained from
dbFieldInfo(DBS_BLOB_POINTER, <nFieldpos>),
BLOBDirectPut(), or BLOBDirectImport().
DBI_BLOB_RECOVER Recovers a damaged BLOB file by correcting its
internal tables. You should run this function
only is dbInfo(DBI_BLOB_INTEGRITY) returns
false (.F.). Note that this function can only
correct the BLOB file's internal tables, it
cannot restore any data that may have become
corrupted.
DBI_BOF Logical value indicating the work area's
beginning of file status (see Bof()).
DBI_CANPUTREC Logical value indicating whether the work area
supports putting records.
DBI_CHILDCOUNT Number of relations set from this work area.
DBI_DB_VERSION String containing version information of the
host RDD. If the optional <expNewSetting>
parameter is provided, and it is one (1), the
result is a more detailed version of the
version being returned.
DBI_DBFILTER Filter expression as a string (see dbFilter()).
DBI_EOF Logical value indicating the work area's end of
file status (see Eof()).
DBI_FCOUNT Number of fields (see FCount()).
DBI_FILEHANDLE Integer representing the DOS file handle for
this database file.
DBI_FOUND Logical value indicating the success or failure
of the last seek operation in the work area
(see Found()).
DBI_FCOUNT Number of fields (see FCount()).
DBI_FULLPATH Returns the full path name of the opened
database file.
DBI_GETDELIMITER Default delimiter.
DBI_GETHEADERSIZE Header size of the file (see Header()).
DBI_GETLOCKARRAY Array of locked records.
DBI_GETRECSIZE Record size of the file (see RecSize()).
DBI_ISDBF Logical value indicating whether the RDD
provides support for the .dbf file format.
DBI_ISFLOCK File lock status.
DBI_LASTUPDATE Last date on which the file was updated (see
LUpdate()).
DBI_LOCKCOUNT Number of locked records.
DBI_LOCKOFFSET Current locking offset as a numeric value.
DBI_MEMOBLOCKSIZE Block size for the memo file associated with
this database.
DBI_MEMOEXT Default extension for the memo file associated
with this database.
DBI_MEMOHANDLE Integer representing the DOS file handle for
the memo file associated with this database
file.
DBI_RDD_VERSION String containing version information of the
RDD for this database. If the optional
<expNewSetting> parameter is provided, and it
is one (1), the result is a more detailed
version of the version being returned.
DBI_SETDELIMITER Default delimiter.
DBI_SHARED Shared flag value.
DBI_TABLEEXT Database file extension.
DBI_VALIDBUFFER Logical value indicating whether the current
buffer is valid.
Important! DBI_USER is a constant that returns the minimum value that third-party RDD developers can use for defining new nInfoType parameters. Values less than DBI_USER are reserved for Computer Associates development.
expNewSetting is reserved for RDDs that allow the file information to be changed, in addition to being retrieved. None of the RDDs supplied with CA-Clipper support this argument. It can be omitted or specified as NIL.
Returns
dbInfo() returns the current setting if expNewSetting is not specified, . If expNewSetting is specified, the previous setting is returned.
Description
dbInfo() retrieves information about a database file. By default, this function operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
Examples
■ The following examples return work area information:
#include dbinfo.ch
? dbInfo(DBI_GETHEADERSIZE) // Same as Header()
? dbInfo(DBI_LASTUPDATE) // Same as LUpdate()
? dbInfo(DBI_GETRECSIZE) // Same as RecSize()
? dbInfo(DBI_FILEHANDLE) // DOS file handle for
// the current database
// file
nInfoType determines the type of information as specified by the constants below. Note, however, that not all constants are supported for all RDDs. These constants are defined in the dbinfo.ch header file, which must be included (#include) in your application.
Order/Index Information Type Constants
Constant Description
DBOI_CONDITION For condition of the specified order as a
string.
DBOI_CUSTOM Logical flag indicating whether the
specified order is custom-built (for RDDs
that support custom-built orders). Note
that although you can turn the custom-
built flag on for a standard order by
specifying true (.T.) for the <uNewSetting>
argument, you cannot turn a custom-built
order into a standard order. Specifying
false (.F.) for <uNewSetting> is the same
as not specifying the argument at all--
both return the current setting.
DBOI_EXPRESSION Order key expression of the specified
order as a string.
DBOI_FILEHANDLE Handle of the specified index file as a
number.
DBOI_HPLOCKING Logical flag indicating whether the
specified index file uses the high
performance index locking schema.
DBOI_INDEXEXT (DBOI_BAGEXT) Default index file extension as a string.
DBOI_INDEXNAME (DBOI_BAGNAME) Name of the specified index file as a
string.
DBOI_ISCOND Logical flag that determines whether the
specified order was defined using a FOR
condition.
DBOI_ISDESC Logical flag that determines if the
specified order is descending. For
drivers that support dynamically setting
the descending flag at runtime, specify
the new value as a logical, using
dbOrderInfo(DBOI_ISDESC, [<cIndexFile>],
[<cOrder> | <nPosition>], <lNewSetting>).
The current setting is returned before it
is changed.
DBOI_KEYADD Logical flag indicating whether a key has
been successfully added to the specified
custom-built order.
DBOI_KEYCOUNT Number of keys in the specified order.
DBOI_KEYDEC Number of decimals in the key of the
specified order.
DBOI_KEYDELETE Logical flag indicating whether a key has
been successfully deleted from the
specified custom-built order.
DBOI_KEYGOTO Logical flag indicating whether the record
pointer has been successfully moved to a
record specified by its logical record
number in the controlling order.
DBOI_KEYSINCLUDED Number of keys included in the specified
order so far. This is primarily useful
for conditional orders. It can be used
during the status display process (with
the EVAL clause of the INDEX command).
DBOI_KEYSIZE Size of the key in the specified order as
a number.
DBOI_KEYTYPE Data type of the key in the specified
order as a string.
DBOI_KEYVAL Key value of the current record from the
controlling order.
DBOI_LOCKOFFSET Locking offset for the specified index
file as a numeric value.
DBOI_NAME Name of the specified order as a string.
DBOI_NUMBER Numeric position of the specified order in
the order list.
DBOI_ORDERCOUNT Number of orders in the specified index
file.
DBOI_POSITION Logical record number of the current
record within the specified order.
DBOI_RECNO Physical record number of the current
record within the specified order.
DBOI_SCOPEBOTTOM Bottom boundary of the scope (as a number)
for the specified order.
DBOI_SCOPEBOTTOMCLEAR Clears the bottom boundary of the scope
for the specified order.
DBOI_SCOPETOP Top boundary of the scope (as a number)
for the specified order.
DBOI_SCOPETOPCLEAR Clears the top boundary of the scope for
the specified order.
DBOI_SETCODEBLOCK Key for the specified order as a code
block.
DBOI_SKIPUNIQUE Logical flag indicating whether the record
pointer has been successfully moved to the
next or previous unique key in the
controlling order.
DBOI_UNIQUE Logical flag indicating whether the
specified order has the unique attribute
set.
Important! DBOI_USER is a constant that returns the minimum value that third-party RDD developers can use for defining new nInfoType parameters. Values less than DBOI_USER are reserved for Computer Associates development.
cIndexFile is the name of an index file, including an optional drive and directory (no extension should be specified). Use this argument with cOrder to remove ambiguity when there are two or more orders with the same name in different index files.
cOrder | nPosition is the name of the order about which you want to obtain information or a number representing its position in the order list. For single-order index files, the order name is the eight-letter index file name. Using the order name is the preferred method since the position may be difficult to determine using multiple-order index files. Invalid values are ignored. If no index file or order is specified, the controlling order is assumed.
expNewSetting is reserved for RDDs that allow the file information to be changed, in addition to being retrieved. None of the RDDs supplied with CA-Clipper support this argument. It can be omitted or specified as NIL.
Returns
If expNewSetting is not specified, dbOrderInfo() returns the current setting. If expNewSetting is specified, the previous setting is returned.
Description
dbOrderInfo() retrieves information about the orders and index files. By default, dbOrderInfo() operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression.
Examples
■ This example uses DBOI_NAME to save the current controlling
order. After changing to a new controlling order, it uses the saved
value to restore the original order:
#include dbinfo.ch
USE Customer INDEX Name, Serial NEW
cOrder := dbOrderInfo(DBOI_NAME) // Name
Customer->dbSetOrder("Serial")
? dbOrderInfo(DBOI_NAME) // Serial
Customer->dbSetOrder(cOrder)
? dbOrderInfo(DBOI_NAME) // Name
■ This example uses aliased expressions to return the default
index file extension (using DBOI_INDEXEXT) in two different work
areas:
#include dbinfo.ch
USE Sales INDEX All_Sales VIA "DBFCDX" NEW
USE Customer INDEX Name, Serial VIA "DBFNTX" NEW
? Sales->dbOrderInfo(DBOI_INDEXEXT) // .CDX
? Customer->dbOrderInfo(DBOI_INDEXEXT) // .NTX
■ In this example, dbOrderInfo(DBOI_INDEXEXT) checks for the
existence of the Customer index file independent of the RDD linked
into the current work area:
#include dbinfo.ch
USE Customer NEW
IF !FILE( "Customer" + dbOrderInfo(DBOI_INDEXEXT))
Customer->dbCreateIndex("Customer", "CustName",;
{||Customer->CustName} )
ENDIF
■ This example accesses the key expression of several orders
from the same index file:
#include dbinfo.ch
USE Customer INDEX All_Cust VIA "DBFMDX" NEW
Customer->dbSetOrder("Serial")
? dbOrderInfo(DBOI_EXPRESSION,, "Name")
// Result: key expression for name order
? dbOrderInfo(DBOI_EXPRESSION,, "Serial")
// Result: key expression for serial order
■ This example uses dbOrderInfo() as part of a TOTAL ON key
expression. Since dbOrderInfo() returns the expression as a string,
it is specified using a macro expression to force evaluation of the
key expression:
#include dbinfo.ch
USE Sales INDEX Salesman NEW
TOTAL ON &(dbOrderInfo(DBOI_EXPRESSION)) ;
FIELDS SaleAmount TO Summary
■ In this example, All_Cust.mdx contains three orders named
CuAcct, CuName, CuZip. The DBOI_INDEXNAME constant is used to
display the name of the index file using one of its orders:
#include dbinfo.ch
USE Customer VIA "DBFNTX" NEW
Customer->dbSetIndex("All_Cust")
? dbOrderInfo(DBOI_INDEXNAME,, "CuName")
// Returns: All_Cust
■ The following example searches for CuName in the order list:
#include dbinfo.ch
USE Customer VIA "DBFNTX" NEW
Customer->dbSetIndex("CuAcct")
Customer->dbSetIndex("CuName")
Customer->dbSetIndex("CuZip")
? dbOrderInfo(DBOI_NUMBER,, "CuName") // 2
■ This example retrieves the FOR condition from an order:
#include dbinfo.ch
USE Customer NEW
INDEX ON Customer->Acct TO Customer ;
FOR Customer->Acct > "AZZZZZ"
? dbOrderInfo(DBOI_CONDITION,, "Customer")
// Returns: Customer->Acct > "AZZZZZ"
dbRecall() causes the current record to be reinstated if it is marked for deletion.
dbRecall() performs the same function as the RECALL command. For more information, refer to the DELETE and RECALL commands.
Notes
■ Logical records: Reinstating a deleted record affects the
record's logical visibility if the global _SET_DELETED status is true (.T.). For more information, refer to the dbDelete() function and the DELETE and RECALL commands.
■ Network environment: For a shared database on a network,
dbRecall() requires the current record to be locked. For more information, refer to the "Network Programming" chapter in the Programming and Utilities Guide.
Examples
■ The following example recalls a record if it is deleted and
attempts to lock the record if successful:
cLast := "Winston"
dbUseArea( .T., "DBFNTX", "Sales", "Sales", .T. )
dbSetIndex( "LASTNAME" )
//
IF ( Sales->(dbSeek(cLast)) )
IF Sales->( Deleted() )
IF Sales( RLock() )
Sales( dbRecall() )
? "Record recalled"
ELSE
"Unable to lock record..."
ENDIF
ENDIF
ELSE
? "Not found"
ENDIF
nInfoType determines the type of information, as specified by the constants below. Note, however, that not all constants are supported for all RDDs. These constants are defined in the dbinfo.ch header file, which must be included (#include) in your application.
Record Information Type Constants
Constant Description
DBRI_DEL Deleted flag status of the record
DBRI_LOCK Locked flag status of the record
DBRI_SIZE Length of the record
DBRI_RECNO Position of the record
DBRI_UPDAT Updated flag status of the record
Important! DBI_USER is a constant that returns the minimum value that third-party RDD developers can use for defining new nInfoType parameters. Values less than DBI_USER are reserved for Computer Associates development.
nRecord is the record to obtain information. If omitted, the current record is used.
expNewSetting is reserved for RDDs that allow the file information to be changed, in addition to being retrieved. None of the RDDs supplied with CA-Clipper support this argument. It can be omitted or specified as NIL.
Returns
If expNewSetting is not specified, dbRecordInfo() returns the current setting. If expNewSetting is specified, the previous setting is returned.
Description
dbRecordInfo() retrieves information about the state of a record (row). The type of information is specified by the nInfoType parameter. By default, this function operates on the currently selected record.
dbRecordInfo() is designed to allow for additional nInfoType values that can be defined by third-party RDD developers.
Examples
■ The following example uses dbRecordInfo() to retrieve field
information:
#include "Dbinfo.ch"
dbRecordInfo(DBRI_SIZE) // Same as RecSize()
dbRecordInfo(DBRI_LOCK, 200) // Is record 200 locked?
dbRecordInfo(DBRI_DEL, 201) // Is record 201 locked?
dbRecordInfo(DBRI_UPDAT) // Is the current record
// updated?
dbRecordInfo(DBRI_RECNO, 230) // On which position is
// record 230?
// If no orders are active,
// the position is 230;
// otherwise, the relative
// position within the order
// will be returned.
Recreate all active indexes for the current work area
Syntax
dbReindex() → NIL
Returns
dbReindex() always returns NIL.
Description
dbReindex() rebuilds all active indexes associated with the current work area. After the indexes are recreated, the work area is moved to the first logical record in the controlling order.
dbReindex() performs the same function as the standard REINDEX command. For more information, refer to the REINDEX command.
Examples
■ The following example reindexes the work area:
cLast := "Winston"
dbUseArea( .T., "DBFNTX", "Sales", "Sales", .T. )
dbSetIndex( "LASTNAME" )
//
IF ( Sales->(dbSeek(cLast)) )
IF RLock()
DELETE FOR Sales->LastName == "Winston"
Sales->( dbReindex() )
ELSE
? "Unable to lock record..."
ENDIF
ELSE
? "Not found"
ENDIF
Return the linking expression of a specified relation
Syntax
dbRelation(<nRelation>) → cLinkExp
Arguments
nRelation is the position of the desired relation in the list of current work area relations. The relations are numbered according to the order in which they were defined with SET RELATION.
Returns
dbRelation() returns a character string containing the linking expression of the relation specified by nRelation. If there is no RELATION SET for nRelation, dbRelation() returns a null string ("").
Description
dbRelation() is a database function used with dbRSelect() to determine the linking expression and work area of an existing relation created with the SET RELATION command.
dbRelation() returns the linking expression defined by the TO clause. dbRSelect() returns the work area linked as defined by the INTO clause.
By default, dbRelation() operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression (see example below).
Notes
■ Declared variables: A character string returned by
dbRelation() may not operate correctly when recompiled and executed using the macro operator (&) if the original expression contained references to local or static variables, or otherwise depends on compile-time declarations.
Examples
■ This example opens three database files, sets two child
relations from the parent work area, and then displays the linking
expression to the second child work area:
USE Invoices INDEX Invoices NEW
USE BackOrder INDEX BackOrder NEW
USE Customer INDEX Customer NEW
SET RELATION TO CustNum INTO Invoices, OrderNum ;
INTO BackOrder
//
? dbRelation(2) // Result: OrderNum
■ Later you can query the same linking expression from an
unselected work area by using an aliased expression like this:
USE Archive NEW
? Customer->(dbRelation(2)) // Result: OrderNum
■ This example is a user-defined function, Relation(), that
returns the results of both dbRelation() and dbRSelect() as an array:
FUNCTION Relation( nRelation )
RETURN { dbRelation(nRelation), ;
Alias(dbRSelect(nRelation)) }
Lock the record at the current or specified identity
Syntax
dbRLock([<xIdentity>]) → lSuccess
Arguments
xIdentity is a unique value guaranteed by the structure of the data file to reference a specific item in a data source (database). In a .dbf xIdentity is the record number. In other data formats, xIdentity is the unique primary key value.
Returns
dbRLock() returns lSuccess, a logical data type that is true (.T.) if successful, false (.F.) if unsuccessful.
Description
dbRLock() is a database function that locks the record identified by the value xIdentity. In Xbase, xIdentity is the record number.
If you do not specify xIdentity, all record locks are released and the current record is locked. If you specify xIdentity, dbRLock() attempts to lock it and, if successful, adds it to the locked record list.
Examples
■ This example shows two different methods for locking multiple
records:
FUNCTION dbRLockRange( nLo, nHi )
LOCAL nRec
FOR nRec := nLo TO nHi
IF ! dbRLock( nRec )
dbRUnlock() // Failed - unlock everything
ENDIF
NEXT
RETURN dbRLockList() // Return array of actual locks
FUNCTION dbRLockArray( aList )
LOCAL nElement, nLen, lRet
lRet := .T.
nLen := Len( aList )
FOR nElement := 1 TO nLen
IF ! dbRLock( aList[ nElement ] )
dbRUnlock() // Failed - unlock everything
lRet := .F.
ENDIF
NEXT
RETURN dbRLockList()
dbRLockList() returns an array of the locked records in the current or aliased work area.
Description
dbRLockList() is a database function that returns a one-dimensional array that contains the identities of record locks active in the selected work area.
Examples
ROCEDURE PrintCurLocks()
OCAL aList
OCAL nSize
OCAL nCount
List := dbRLockList()
Size := Len( aList )
"Currently locked records: "
OR nCount := 1 TO nSize
?? aList[ nCount ]
?? Space( 1 )
NEXT
?
RETURN
nRelation is the position of the desired relation in the list of current work area relations. The relations are numbered according to the order in which they were defined with SET RELATION.
Returns
dbRSelect() returns the work area number of the relation specified by nRelation as an integer numeric value. If there is no RELATION SET for nRelation, dbRSelect() returns zero.
Description
dbRSelect() is a database function used in combination with dbRelation() to determine the work area and linking expression of an existing relation created with the SET RELATION command. dbRSelect() returns the work area defined by the INTO clause. dbRelation() returns the linking expression defined by the TO clause. To determine the alias of the relation instead of the work area number, use the expression Alias(dbRSelect(nRelation)).
By default, dbRSelect() operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression (see example below).
Examples
■ This example opens three database files, sets two child
relations from the parent work area, and then displays the linking
expression to the second child work area, as well as the target work
area of the relation:
USE Invoices INDEX Invoices NEW
USE BackOrder INDEX BackOrder NEW
USE Customer INDEX Customer NEW
SET RELATION TO CustNum INTO Customer, ;
OrderNum INTO BackOrder
//
? dbRelation(2), dbRSelect(2) // Result: OrderNum 3
? Alias(dbRSelect(2)) // Result: BACKORDER
■ Later, you can query the same information from an unselected
work area by using an aliased expression:
USE Archive NEW
? Customer->(dbRelation(2)) // Result: OrderNum
? Customer->(dbRSelect(2)) // Result: 3
xIdentity is a unique value guaranteed by the structure of the data file to reference a specific item in a data source (database). In a .dbf xIdentity is the record number. In other data formats, xIdentity is the unique primary key value.
Returns
dbRUnlock() always returns NIL.
Description
dbRUnlock() is a database function that releases the lock on xIdentity and removes it from the Lock List. If xIdentity is not specified, all record locks are released.
Examples
PROCEDURE dbRUnlockRange( nLo, nHi )
LOCAL nCounter
// Unlock the records in the range from nLo to nHi
FOR nCounter := nLo TO nHi
dbRUnlock( nCounter )
NEXT
RETURN
expKey is a value of any type that specifies the key value associated with the desired record.
lSoftSeek is an optional logical value that specifies whether a soft seek is to be performed. This determines how the work area is positioned if the specified key value is not found (see below). If lSoftSeek is omitted, the current global _SET_SOFTSEEK setting is used.
lLast is specified as true (.T.) to seek the last occurrence of the specified key value. False (.F.), the default, seeks the first occurrence.
Note: This parameter is only supported for specific RDDs. DBFNTX is NOT one of them.
Returns
dbSeek() returns true (.T.) if the specified key value was found; otherwise, it returns false (.F.).
Description
dbSeek() moves to the first logical record whose key value is equal to expKey. If such a record is found, it becomes the current record and dbSeek() returns true (.T.); otherwise, it returns false (.F.). the positioning of the work area is as follows: for a normal (not soft) seek, the work area is positioned to LastRec() + 1 and Eof() returns true (.T.); for a soft seek, the work area is positioned to the first record whose key value is greater than the specified key value. If no such record exists, the work area is positioned to LastRec() + 1 and Eof() returns true (.T.).
For a work area with no active indexes, dbSeek() has no effect.
dbSeek() performs the same function as the standard SEEK command. For more information, refer to the SEEK command.
Notes
■ Logical records: dbSeek() operates on logical records which
are considered in indexed order. If a filter is set, only records which meet the filter condition are considered.
■ Controlling order: If the work area has more than one active
index, the operation is performed using the controlling order as set by dbSetOrder() or the SET ORDER command. For more information, refer to the SET ORDER command.
■ Network environment: For a shared file on a network, moving
to a different record may cause updates to the current record to become visible to other processes. For more information, refer to the "Network Programming" chapter in the Programming and Utilities Guide. This function will not affect the locked status of any record.
Examples
■ In this example, dbSeek() moves the pointer to the record in
the database, Employee, in which the value in FIELD "cName" matches
the entered value of cName:
ACCEPT "Employee name: " TO cName
IF ( Employee->(dbSeek(cName)) )
Employee->(VIEWRECORD())
ELSE
? "Not found"
END
nArea is a numeric value between zero and 250, inclusive, that specifies the work area being selected.
cAlias is a character value that specifies the alias of a currently occupied work area being selected.
Returns
dbSelectArea() always returns NIL.
Description
dbSelectArea() causes the specified work area to become the current work area. All subsequent database operations will apply to this work area unless another work area is explicitly specified for an operation. dbSelectArea() performs the same function as the standard SELECT command. For more information, refer to the SELECT command.
Notes
■ Selecting zero: Selecting work area zero causes the lowest
numbered unoccupied work area to become the current work area.
■ Aliased expressions: The alias operator (->) can temporarily
select a work area while an expression is evaluated and automatically restore the previously selected work area afterward. For more information, refer to the alias operator (->).
Examples
■ The following example selects a work area via the alias name:
cLast := "Winston"
dbUseArea( .T., "DBFNTX", "Sales", "Sales", .T. )
dbSetIndex( "SALEFNAM" )
dbSetIndex( "SALELNAM" )
//
dbUseArea( .T., "DBFNTX", "Colls", "Colls", .T. )
dbSetIndex( "COLLFNAM" )
dbSetIndex( "COLLLNAM" )
//
dbSelectArea( "Sales" ) // select "Sales" work area
//
IF ( Sales->(dbSeek(cLast)) )
IF Sales->( Deleted() ) .AND. Sales->( RLock() )
Sales->( dbRecall() )
? "Deleted record has been recalled."
ENDIF
ELSE
? "Not found"
ENDIF
Return the default database driver and optionally set a new driver
Syntax
dbSetDriver([<cDriver>]) → cCurrentDriver
Arguments
cDriver is an optional character value that specifies the name of the database driver that should be used to activate and manage new work areas when no driver is explicitly specified.
Returns
dbSetDriver() returns the name of the current default driver.
Description
dbSetDriver() sets the database driver to be used when activating new work areas without specifying a driver. If the specified driver is not available to the application, the call has no effect. dbSetDriver() returns the name of the current default driver, if any.
Examples
■ This example makes the "DBFNDX" driver the default driver. If
the driver is unavailable, a message is issued:
dbSetDriver("DBFNDX")
IF ( dbSetDriver() <> "DBFNDX" )
? "DBFNDX driver not available"
ENDIF
bCondition is a code block that expresses the filter condition in executable form.
cCondition stores the filter condition as a character string for later retrieval by the dbFilter() function. If you omit this optional parameter, the dbFilter() function will return an empty string for the work area.
Returns
dbSetFilter() always returns NIL.
Description
dbSetFilter() sets a logical filter condition for the current work area. When a filter is set, records which do not meet the filter condition are not logically visible. That is, database operations which act on logical records will not consider these records.
The filter expression supplied to dbSetFilter() evaluates to true (.T.) if the current record meets the filter condition; otherwise, it should evaluate to false (.F.).
The filter expression may be a code block (bCondition) or both a code block and equivalent text (cCondition). If both versions are supplied, they must express the same condition. If the text version is omitted, dbFilter() will return an empty string for the work area.
dbSetFilter() performs the same function as the standard SET FILTER command. For more information, refer to the SET FILTER command.
Notes
■ Logical records: dbSetFilter() affects the logical visibility
of records (see above).
■ Side effects: Setting a filter condition is only guaranteed to
restrict visibility of certain records as described above. The filter expression is not necessarily evaluated at any particular time, by any particular means, or on any particular record or series of records. If the filter expression relies on information external to the database file or work area, the effect is unpredictable. If the filter expression changes the state of the work area (e.g., by moving to a different record or changing the contents of a record), the effect is unpredictable.
■ Evaluation context: When the filter expression is evaluated,
the associated work area is automatically selected as the current work area before the evaluation; the previously selected work area is automatically restored afterward.
Examples
■ This example limits data access to records in which the Age
field value is less than 40:
USE Employee NEW
dbSetFilter( {|| Age < 40}, "Age < 40" )
dbGoTop()
Empty orders from an order bag into the order list
Syntax
dbSetIndex(<cOrderBagName>) → NIL
Arguments
cOrderBagName is the name of a disk file containing one or more orders. You may specify cOrderBagName as the file name with or without the path name or extension. If you do not include the extension as part of cOrderBagName, CA-Clipper uses the default extension of the current RDD.
Returns
dbSetIndex() always returns NIL.
Description
dbSetIndex() is a database function that adds the contents of an order bag into the order list of the current work area. Any orders already associated with the work area continue to be active. If the newly opened order bag is the only order associated with the work area, it becomes the controlling order; otherwise, the controlling order remains unchanged. If the order bag contains more than one order, and there are no other orders associated with the work area, the first order in the new order bag becomes the controlling order.
Note: dbSetIndex() does not close all currently open index files.
dbSetIndex() is a compatibility command and therefore is not recommended. It is superseded by the ordListAdd() function.
Examples
USE Customer NEW
dbSetIndex( "Cust01" ) // Open the index Cust01
// in the current work area
dbSetIndex( "Cust02" ) // Open the index Cust02
// leaving Cust01 open
nOrderNum is a numeric value that specifies which of the active indexes is to be the controlling index.
Returns
dbSetOrder() always returns NIL.
Description
dbSetOrder() controls which of the current work area's active indexes is the controlling index. The controlling index is the index which determines the logical order of records in the work area.
Active indexes are numbered from 1 to the number of active indexes, based on the order in which the indexes were opened. nOrderNum specifies the number of the desired index.
dbSetOrder() performs the same function as the standard SET ORDER command. For more information, refer to the SET ORDER command.
Notes
■ Setting order to zero: Setting order to zero causes the work
area to be accessed in natural (record number) order. Only the logical order of the records is affected; any open indexes continue to be active and are properly maintained.
Examples
■ This example sets the second named index, Age, as the
controlling index:
USE Employee NEW
SET INDEX TO Name, Age
dbSetOrder(2)
nArea is a numeric value that specifies the work area number of the child work area.
cAlias is a character value that specifies the alias of the child work area.
bExpr is a code block that expresses the relational expression in executable form.
cExpr is a character value that expresses the relational expression in textual form.
Returns
dbSetRelation() always returns NIL.
Description
dbSetRelation() relates the work area specified by nArea or cAlias (the child work area) to the current work area (the parent work area). Any existing relations remain active.
Relating work areas synchronizes the child work area with the parent work area. This is achieved by automatically repositioning the child work area whenever the parent work area moves to a new record. If there is an active index in the child work area, moving the parent work area causes an automatic SEEK operation in the child work area; the seek key is based on the expression specified by bExpr and/or cExpr. If the child work area has no active index, moving the parent work area causes an automatic GOTO in the child work area; the record number for the GOTO is based on the expression specified by bExpr and/or cExpr.
The relational expression may be a code block (bExpr) or both a code block and equivalent text (cExpr). If both versions are supplied, they must be equivalent. If the text version is omitted, dbRelation() will return an empty string for the relation.
dbSetRelation() performs the same function as the standard SET RELATION command with the ADDITIVE clause. For more information, refer to the SET RELATION command.
Notes
■ Side effects: dbSetRelation() is only guaranteed to
synchronize the work areas as described above. The relational expression is not necessarily evaluated at any particular time, by any particular means, or on any particular record or series of records. If the relational expression relies on information external to the parent work area or its associated database file, the effect is unpredictable. If the expression changes the state of either work area (e.g., by moving to a different record or changing the contents of a record), the effect is unpredictable.
■ Evaluation context: When the relational expression is
evaluated, the parent work area is automatically selected as the current work area before the evaluation; the previously selected work area is automatically restored afterward.
■ Soft seeking: Seek operations that occur as part of relational
positioning are never soft seeks. If a relational movement is unsuccessful, the child work area is positioned to LastRec() + 1, its Found() status returns false (.F.), and its Eof() status returns true (.T.).
Examples
■ This example demonstrates a typical use of the dbSetRelation()
function:
USE Employee NEW
USE Department NEW INDEX Dept
SELECT Employee
dbSetRelation("Department", {|| Employee->Dept},;
"Employee->Dept")
LIST Employee->Name, Department->Name
nRecords is the number of logical records to move, relative to the current record. A positive value means to skip forward, and a negative value means to skip backward. If nRecords is omitted, a value of 1 is assumed.
Returns
dbSkip() always returns NIL.
Description
dbSkip() moves either forward or backward relative to the current record. Attempting to skip forward beyond the last record positions the work area to LastRec() + 1 and Eof() returns true (.T.). Attempting to skip backward beyond the first record positions the work area to the first record and Bof() returns true (.T.).
dbSkip() performs the same function as the standard SKIP command. For more information, refer to the SKIP command.
Notes
■ Logical records: dbSkip() operates on logical records. If
there is an active index, records are considered in indexed order. If a filter is set, only records which meet the filter condition are considered.
■ Controlling order: If the work area has more than one active
index, the skip operation is performed using the controlling order as set by dbSetOrder() or the SET ORDER command. For more information, refer to the SET ORDER command.
■ Network environment: For a shared file on a network, moving to
a different record may cause updates to the current record to become visible to other processes. For more information, refer to the "Network Programming" chapter in the Programming and Utilities Guide.
Examples
■ This example demonstrates a typical use of the dbSkip()
function:
dbGoTop()
DO WHILE ( !Eof() )
? FIELD->Name
dbSkip()
ENDDO
Create an array containing the structure of a database file
Syntax
dbStruct() → aStruct
Returns
dbStruct() returns the structure of the current database file in an array whose length is equal to the number of fields in the database file. Each element of the array is a subarray containing information for one field. The subarrays have the following format:
dbStruct() Return Array
Position Metasymbol Dbstruct.ch
1 cName DBS_NAME
2 cType DBS_TYPE
3 nLength DBS_LEN
4 nDecimals DBS_DEC
If there is no database file in USE in the current work area, dbStruct() returns an empty array ({}).
Description
dbStruct() is a database function that operates like COPY STRUCTURE EXTENDED by creating an array of structure information rather than a database file of structure information. There is another function, dbCreate(), that can create a database file from the structure array.
By default, dbStruct() operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression as shown below.
Note, a header file, dbstruct.ch, located in \CLIP53\INCLUDE contains a series of manifest constants for each field attribute.
Examples
■ This example opens two database files and then creates an
array containing the database structure using dbStruct() within an
aliased expression. The field names are then listed using AEval():
#include "Dbstruct.ch"
//
LOCAL aStruct
USE Customer NEW
USE Invoices NEW
//
aStruct := Customer->(dbStruct())
AEval( aStruct, {|aField| QOut(aField[DBS_NAME])} )
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, header file is dbstruct.ch.
dbUnlock() releases any record or file locks obtained by the current process for the current work area. dbUnlock() is only meaningful on a shared database in a network environment.
dbUnlock() performs the same function as the standard UNLOCK command. For more information, refer to the UNLOCK command.
Notes
■ Network environment: Releasing locks may cause updates to the
database to become visible to other processes. For more information, refer to the "Network Programming" chapter in the Programming and Utilities Guide.
Examples
■ The following example illustrates a basic use of the
dbUnlock() function:
cLast := "Winston"
USE Sales SHARED NEW VIA "DBFNTX"
dbSetIndex( "LASTNAME" )
//
IF ( Sales->(dbSeek(cLast)) )
IF Sales->( RLock() )
Sales->( dbDelete() )
? "Record deleted: ", Sales( Deleted() )
Sales->( dbUnlock() )
ELSE
? "Unable to lock record..."
ENDIF
ELSE
? "Not found"
ENDIF
dbUnlockAll() releases any record or file locks obtained by the current process for any work area. dbUnlockAll() is only meaningful on a shared database in a network environment. It is equivalent to calling dbUnlock() on every occupied work area.
dbUnlockAll() performs the same function as the UNLOCK ALL command. For more information, refer to the UNLOCK ALL command.
Examples
■ The following example marks a record for deletion if an
RLock() attempt is successful, then clears all locks in all work
areas:
cLast := "Winston"
USE Sales SHARED NEW VIA "DBFNTX"
dbSetIndex( "SALEFNAM" )
dbSetIndex( "SALELNAM" )
//
USE Colls SHARED NEW VIA "DBFNTX"
dbSetIndex( "COLLFNAM" )
dbSetIndex( "COLLLNAM" )
//
dbSelectArea( "Sales" ) // select "Sales" work area
//
IF ( Colls->(dbSeek(cLast)) )
IF Colls->( Deleted() )
? "Record deleted: ", Colls->( Deleted() )
IF Colls->( RLock() )
Colls->( dbRecall() )
? "Record recalled..."
ENDIF
ENDIF
ELSE
? "Not found"
dbUnlockAll() // remove all locks in
ENDIF // all work areas
lNewArea is an optional logical value. A value of true (.T.) selects the lowest numbered unoccupied work area as the current work area before the use operation. If lNewArea is false (.F.) or omitted, the current work area is used; if the work area is occupied, it is closed first.
cDriver is an optional character value. If present, it specifies the name of the database driver which will service the work area. If cDriver is omitted, the current default driver is used (see note below).
cName specifies the name of the database (.dbf) file to be opened.
xcAlias is an optional character value. If present, it specifies the alias to be associated with the work area. The alias must constitute a valid CA-Clipper identifier. A valid xcAlias may be any legal identifier (i.e., it must begin with an alphabetic character and may contain numeric or alphabetic characters and the underscore). Within a single application, CA-Clipper will not accept duplicate aliases. If xcAlias is omitted, a default alias is constructed from cName.
lShared is an optional logical value. If present, it specifies whether the database (.dbf) file should be accessible to other processes on a network. A value of true (.T.) specifies that other processes should be allowed access; a value of false (.F.) specifies that the current process is to have exclusive access. If lShared is omitted, the current global _SET_EXCLUSIVE setting determines whether shared access is allowed.
lReadonly is an optional logical value that specifies whether updates to the work area are prohibited. A value of true (.T.) prohibits updates; a value of false (.F.) permits updates. A value of true (.T.) also permits read-only access to the specified database (.dbf) file. If lReadonly is omitted, the default value is false (.F.).
Returns
dbUseArea() always returns NIL.
Description
dbUseArea() associates the specified database (.dbf) file with the current work area. It performs the same function as the standard USE command. For more information, refer to the USE command.
Notes
■ Current driver: If no driver is specified in the call to
dbUseArea() the default driver is used. If more than one driver is available to the application, the default driver is the driver specified in the most recent call to dbSetDriver(). If dbSetDriver() has not been called, the DBFNTX driver is used. If the default driver is undetermined, DBFNTX will be used.
Examples
■ This example is a typical use of the dbUseArea() function:
dbUseArea(.T., "DBFNDX", "Employees")
Date() is a date function that provides a means of initializing memory variables to the current date, comparing other date values to the current date, and performing date arithmetic relative to the current date.
The display format for dates is controlled by the SET DATE command. The default format is mm/dd/yy.
Examples
■ These examples show the Date() function used in various ways:
? Date() // Result: 09/01/90
? Date() + 30 // Result: 10/01/90
? Date() - 30 // Result: 08/02/90
dDate := Date()
? CMonth(dDate) // Result: September
Day() returns a number in the range of zero to 31 as an integer numeric value. If the month is February, leap years are considered. If the date argument is February 29 and the year is not a leap year, Day() returns zero. If the date argument is empty, Day() returns zero.
Description
Day() is a date conversion function used to convert a date value to the day of a month. This function is used in combination with CMonth() and Year() to format dates. In addition, it is often used in various date calculations.
Examples
■ These examples show the Day() function used several ways:
? Date() // Result: 09/01/90
? Day(Date()) // Result: 1
? Day(Date()) + 1 // Result: 2
? Day(CToD("12/01/94")) // Result: 1
■ This example uses Day() in combination with CMonth() and
Year() to format a date value:
? CMonth(Date()) + Str(Day(Date())) +;
"," + Str(Year(Date())) // Result: June 15, 1990
Dbf() returns the alias of the current work area as a character string. If there is no active database file in the current work area, Dbf() returns a null string ("").
Description
Dbf() is a compatibility function that replicates the Dbf() function in dBASE III PLUS. CA-Clipper implements it by invoking the Alias() function without an argument.
Dbf() is a compatibility function and, therefore, no longer recommended. It is superseded entirely by the Alias() function.
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/DBF.PRG
Deleted() returns true (.T.) if the current record is marked for deletion; otherwise, it returns false (.F.). If there is no database file in USE in the current work area, Deleted() returns false (.F.).
Description
Deleted() is a database function that determines if the current record in the active work area is marked for deletion. Since each work area with an open database file can have a current record, each work area has its own Deleted() value.
By default, Deleted() operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression (see example below).
In applications, Deleted() is generally used to query the deleted status as a part of record processing conditions, or to display the deleted status as a part of screens and reports.
Examples
■ This example uses Deleted() in the current and in an
unselected work area:
USE Customer NEW
USE Sales NEW
? Deleted() // Result: .F.
DELETE
? Deleted() // Result: .T.
? Customer->(Deleted()) // Result: .F.
■ This example uses Deleted() to display a record's deleted
status in screens and reports:
@ 1, 65 SAY IF(Deleted(), "Inactive", "Active")
exp is any valid expression of character, date, logical, or numeric type. Memo type is treated in the same way as character type.
Returns
Descend() returns an inverted expression of the same data type as the exp, except for dates which return a numeric value. A Descend() of Chr(0) always returns Chr(0).
Description
Descend() is a conversion function that returns the inverted form of the specified expression to be used with INDEX to create descending order indexes. Specify that part of the index expression you want to be descending as the Descend() argument. To subsequently perform a lookup with SEEK, specify Descend() in the search expression.
Notes
■ The preferred way to create a descending index is to use the
DESCENDing clause of the INDEX command. Using DESCENDING is the same as specifying the Descend() function, but without the performance penalty during index updates. If you create a DESCENDING index, you will not need to use the Descend() function during a SEEK. DESCENDING is an attribute of the index (.ntx) file, where it is stored and used for REINDEXing purposes.
Examples
■ This example uses Descend() in an INDEX expression to create a
descending order date index:
USE Sales NEW
INDEX ON Descend(OrdDate) TO SalesDate
Later, use Descend() to SEEK on the descending index:
SEEK Descend(dFindDate)
■ This example illustrates how to create a descending order
index using more than one data type. Here, the key is created using
the concatenation of date and character fields after the appropriate
type conversion has taken place. This example uses Str() instead of
DToS(), since Descend() of a date returns a numeric value:
USE Sales NEW
INDEX ON Str(Descend(SaleDate)) + Salesman TO LastSale
cColorString is an optional argument that defines the display color of exp. If the current DEVICE setting is SCREEN, the output is displayed in the specified color.
If not specified, exp is displayed as the standard color of the current system color as defined by SetColor(). cColorString is a character expression containing the standard color setting. If you want to specify a literal color setting, enclose it in quote marks.
Returns
DevOut() always returns NIL.
Description
DevOut() is a full-screen display function that writes the value of a single expression to the current device at the current cursor or printhead position. Use DevOut() with DevPos() in std.ch to implement the @...SAY command.
Examples
■ This example shows the relationship between the DevOut()
function and the @...SAY command:
DevPos(10, 10)
DevOut("Hello there", "BG+/B"))
//
@ 10, 10 SAY "Hello there" COLOR "BG+/B"
cPicture defines the formatting control for the display of exp. The picture specified here is the same as one used with @...SAY or TRANSFORM and can include both templates and functions.
cColorString is an optional argument that defines the display color of exp. If the current DEVICE is SCREEN, output displays in the specified color.
If not specified, exp displays as the standard color of the current system color as defined by SetColor(). cColorString is a character expression containing the standard color setting. If you want to specify a literal color setting, it must be enclosed in quote marks.
Returns
DevOutPict() always returns NIL.
Description
DevOutPict() is a full-screen display function that writes the value of a single expression to the current device at the current cursor or printhead position. DevOutPict() is used in combination with DevPos() in std.ch to implement the @...SAY command used with a PICTURE clause.
Examples
■ This example shows the relationship between the DevOutPict()
function and the @...SAY command:
DevPos(10, 10)
DevOutPict("Hello there", "@!", "BG+/B"))
//
@ 10, 10 SAY "Hello there" PICTURE "@!" COLOR "BG+/B"
Move the cursor or printhead to a new position depending on the current device
Syntax
DevPos(<nRow>, <nCol>) → NIL
Arguments
nRow and nCol are the new row and column positions of the cursor or printhead.
Returns
DevPos() always returns NIL.
Description
DevPos() is an environment function that moves the screen or printhead depending on the current DEVICE. If DEVICE is SET to SCREEN, DevPos() behaves like SetPos(), moves the cursor to the specified location, and updates Row() and Col() with the new cursor position.
If DEVICE is SET to PRINTER, DevPos() moves the printhead instead. It does this by sending the number of linefeed and/or formfeed characters to the printer, and advancing the printhead to the new position. If the current SET MARGIN value is greater than zero, it is added to nCol. The printhead is then advanced to the specified nRow and nCol position and PRow() and PCol() are updated. If either nRow or nCol are less than the current PRow() and PCol() values, the printhead is moved according to the following special rules:
■ If nRow is less than PRow(), an automatic EJECT (Chr(12)) is
sent to the printer followed by the number of linefeed characters (Chr(10)) required to position the printhead on nRow of the following page.
■ If nCol including the current SET MARGIN value is less than
PCol(), a carriage return character (Chr(13)) and the number of space characters required to position the printhead at nCol are sent to the printer.
To circumvent these rules, use SetPRC() to reset PRow() and PCol() to new values before using DevPos(). See the SetPRC() discussion for more information.
If the printer is redirected to a file using the SET PRINTER command, DevPos() updates the file instead of the printer.
Create and initialize private memory variables and arrays
Syntax
DECLARE <identifier> [[:= <initializer>], ... ]
Arguments
identifier is the name of a private variable or array to create. If the identifier is followed by square brackets ([ ]), it is created as an array. If the identifier is an array, the syntax for specifying the number of elements for each dimension is either array[nElements, nElements2,...] or array[nElements][nElements2]... The maximum number of elements per dimension is 4096.
initializer is the optional assignment of a value to a new private variable. An initializer expression for a private variable consists of the inline assignment operator (:=) followed by any valid CA-Clipper expression, including a literal array. If no explicit initializer is specified, the variable is given an initial value of NIL. In the case of an array, each element is NIL. Array identifiers, cannot be given values with an initializer.
DECLARE can create and, optionally, initialize a list of variable arrays, if definitions are separated by commas.
Description
DECLARE is a compatibility statement that is a synonym for the PRIVATE statement. Its general use is not recommended. PRIVATE should be used in all instances.
scope is the portion of the current database file to DELETE. If a scope is not specified, DELETE acts only on the current record. If a conditional clause is specified, the default becomes ALL records.
WHILElCondition specifies the set of records meeting the condition from the current record until the condition fails.
FORlCondition specifies the conditional set of records to DELETE within the given scope.
Description
DELETE is a database command that tags records so they can be filtered with SET DELETED ON, queried with Deleted(), or physically removed from the database file with PACK. In addition, display commands such as LIST and DISPLAY identify deleted records with an asterisk (*) character. Once records are deleted, you can reinstate them by using RECALL. If you want to remove all records from a database file, use ZAP instead of DELETE ALL and PACK.
Any deleted record can be recalled as long as the PACK or ZAP command has not been issued. Once the PACK or ZAP command has been issued, the deleted data cannot be retrieved.
In a network environment, DELETE requires the current record be locked with RLock() if you are deleting a single record. If you are deleting several records, the current database file must be locked with FLock() or USEed EXCLUSIVEly. Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information.
Notes
■ DELETE with SET DELETED ON: If the current record is deleted
with SET DELETED ON, it will be visible until the record pointer is moved.
Examples
■ This example demonstrates use of the FOR clause to mark a set
of records for deletion:
USE Sales INDEX Salesman NEW
DELETE ALL FOR Inactive
xcFile is the name of the file to be deleted from disk and can be specified either as a literal file name or as a character expression enclosed in parentheses. You must specify the file name, including the extension, and it may optionally be preceded by a drive and/or path specification.
Description
DELETE FILE, a synonym for ERASE, is a file command that removes the specified file from disk. SET DEFAULT and SET PATH do not affect DELETE FILE. The file is deleted from disk only if found in the current DOS directory or in the directory explicitly specified as part of the file name.
Warning! Files must be CLOSEd before deleting them. Otherwise, either a sharing violation or a date corruption on the drive may occur.
Examples
■ This example removes a specified file from disk then tests to
see if the file was in fact removed:
? FILE("Temp.dbf") // Result: .T.
DELETE FILE Temp.dbf
? FILE("Temp.dbf") // Result: .F.
DELETE TAG <cOrderName> [IN <xcOrderBagName>]
[, <cOrderName> [IN xcOrderBagName] list>]
Arguments
cOrderName is a character string that represents the order name.
xcOrderBagName is the name of a disk file containing one or more orders. You may specify xcOrderBagName as the file name with or without the path name or appropriate extension. If you do not include the extension as part of xcOrderBagName, CA-Clipper uses the default extension of the current RDD.
cOrderName ...list is an optional list of order and order bag name pairs, separated by commas. Any reference to cOrderName that results in either a null string ("") or spaces is ignored. You can specify each order as a literal expression or as a character expression enclosed in parentheses. If you specify no extension for the order bag name, the current database driver supplies a default extension.
Description
This command removes an order from an order bag in the current or specified work area. If you do not specify an xcOrderBagName, all orders bags are searched in the current or specified work area. The first occurrence of cOrderName is deleted. A runtime recoverable error is raised if the order is not found.
If cOrderName is the active order, the database in the current or specified work area reverts to its identity order (natural or entry) and SET FILTER scoping.
A runtime error is raised if xcOrderBagName does not exist or if it exists but does not contain cOrderName.
The active RDD determines the order capacity of an order bag. The default DBFNTX and the DBFNDX drivers only support single-order bags, while other RDDs may support multiple-order bags (e.g., the DBFCDX and DBFMDX drivers).
Examples
USE Customer VIA "DBFCDX" NEW
SET INDEX TO Customer
// Delete the Orders (Tags) Cust01 and Cust02 that
// exist in the index file Customer
DELETE TAG Cust01 IN Customer
DELETE TAG Cust02 IN Customer
// or
// DELETE TAG Cust01 IN Customer, Cust02 IN Customer
cDir is the name of the directory to change to, including the drive.
Returns
DirChange() returns 0 if successful; -1 if there is an argument error. Otherwise, DirChange() returns the DOS error code.
Description
DirChange() changes the current DOS directory. This function may also be used to determine whether or not a directory exists.
Examples
■ The following example attempts to change to the "c:\dos"
directory. If it is unsuccessful, an error message is displayed.
nResult := DirChange("c:\dos")
IF nResult != 0
? "Cannot change directory. "
DO CASE
CASE nResult == 3
?? "Directory does not exist."
CASE nResult == 5
?? "Access to directory denied."
END
BREAK
ENDIF
You may also use something like this:
DirChange( "..\..\test" )
cDirSpec identifies the drive, directory and file specification for the directory search. Wildcards are allowed in the file specification. If cDirSpec is omitted, the default value is *.*.
cAttributes specifies inclusion of files with special attributes in the returned information. cAttributes is a string containing one or more of the following characters:
Directory() Attributes
Attribute Meaning
H Include hidden files
S Include system files
D Include directories
V Search for the DOS volume label and exclude all other files
Normal files are always included in the search, unless you specify V.
Returns
Directory() returns an array of subarrays, with each subarray containing information about each file matching cDirSpec. The subarray has the following structure:
Directory() Subarray Structure
Position Metasymbol Directry.ch
1 cName F_NAME
2 cSize F_SIZE
3 dDate F_DATE
4 cTime F_TIME
5 cAttributes F_ATTR
If no files are found matching cDirSpec or if cDirSpec is an illegal path or file specification, Directory() returns an empty ({}) array.
Description
Directory() is an environment function that returns information about files in the current or specified directory. It is similar to ADir(), but returns a single array instead of adding values to a series of existing arrays passed by reference.
Use Directory() to perform actions on groups of files. In combination with AEval(), you can define a block that can be applied to all files matching the specified cDirSpec.
The header file, directry.ch, in the \CLIP53\INCLUDE subdirectory contains #defines for the subarray subscripts, so that the references to each file subarray are more readable.
Examples
■ This example creates an array of information about files in
the current directory and then lists the names of the files using
AEval() and QOut():
#include "Directry.ch"
//
aDirectory := Directory("*.*", "D")
AEval( aDirectory, {|aFile| QOut(aFile[F_NAME])} )
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, header file is directry.ch.
cNewDir is the name of the directory to be created, including an optional drive. If you do not specify a drive, the current one is used.
Returns
DirMake() returns 0 if successful; -1 if there is an argument error. Otherwise, DirMake() returns the DOS error code.
Description
DirMake() creates a specified directory. Note that first you must have sufficient rights to create a directory. To create nested subdirectories, you must create each subdirectory separately, starting from the top-level directory that you want to create (see example below.)
Examples
■ This example assumes that C:\TEST exists and uses DirMake()
twice to create a nested subdirectory under it:
DirMake("c:\test\one") // Create top-most one
nResult := DirMake("c:\test\one\two")
IF nResult != 0
? "Cannot make directory, DOS error ", nResult
BREAK
ENDIF
You may also use something like this:
DirMake( ".\test" )
cDirName is the name of the directory to erase, including an optional drive. If you do not specify a drive, the current one is used.
Returns
DirRemove() returns 0 if successful; -1 if there is an argument error. Otherwise, DIRREMOVE returns the DOS error code.
Description
DirRemove() removes a specified directory. Note that you must first have sufficient rights to delete a directory. A directory must be empty in order to be deleted. Therefore, to delete a directory that contains subdirectories, you must first delete the subdirectories (see example below).
Examples
■ This example uses DirRemove() to delete a subdirectory named
C:\TEST\ONE, which only contains an empty subdirectory named
C:\TEST\ONE\TWO:
DirRemove("c:\test\one\two") // First delete lowest dir
nResult := DirRemove("c:\test\one") // Then delete higher dir
IF nResult != 0
? "Cannot remove directory, DOS error ", siResult
BREAK
ENDIF
cDrive specifies the letter of the disk drive to change to.
Returns
DiskChange() returns true (.T.) if successful; otherwise, it returns false (.F.).
Examples
■ This example uses DiskChange() to change to drive "D":
IF DiskChange("D:")
? "Successfully changed"
ELSE
? "Not changed"
ENDIF
■ This example builds a string that contains all currently
available drives on your system:
FUNCTION AllDrives()
LOCAL wI, cDrives := ""
FOR wI := 1 TO 26
IF DiskChange( Chr(wI + 64) )
cDrives := cDrives + Chr(wI + 64)
ENDIF
NEXT
RETURN cDrives
DiskName() returns the letter of the current DOS drive, without a trailing colon.
Examples
■ This example illustrates the relationship between
DiskName()and DiskChange() and shows that DiskName() is unaffected by
the SET DEFAULT TO command:
? DiskName() // C
SET DEFAULT TO A
? DiskName() // C
DiskChange("A")
? DiskName() // A
DiskChange("C")
? DiskName() // C
nDrive is the number of the drive to query, where one is drive A, two is B, three is C, etc. The default is the current DOS drive if nDrive is omitted or specified as zero.
Returns
DiskSpace() returns the number of bytes of empty space on the specified disk drive as an integer numeric value.
Description
DiskSpace() is an environment function that determines the number of available bytes remaining on the specified disk drive. It is useful when COPYing or SORTing to another drive to determine if there is enough space available before initiating the operation. You may also use DiskSpace() with RecSize() and RecCount() to create a procedure to back up database files.
DiskSpace() ignores the SET DEFAULT drive setting.
Examples
■ This example is a user-defined function that demonstrates the
use of DiskSpace() to back up a database file to another drive:
FUNCTION BackUp( cTargetFile, cTargetDrive )
LOCAL nSpaceNeeded, nTargetDrive
//
nSpaceNeeded := INT((RecSize() * ;
LastRec()) + Header() + 1)
nTargetDrive := Asc(Upper(cTargetDrive)) - 64
//
IF DiskSpace(nTargetDrive) < nSpaceNeeded
RETURN .F.
ENDIF
COPY TO (cTargetDrive + ":" + cTargetFile)
//
RETURN .T.
DispBegin() is a screen function that informs the CA-Clipper display output system that the application is about to perform a series of display operations.
Use DispBegin() with DispEnd() to allow the display output system to buffer display updates. Display output which occurs after DispBegin() but before DispEnd() is allowed to accumulate in internal buffers. When DispEnd() executes, any pending updates appear on the physical display. This is useful in applications where complex screen displays are slow and the appearance of performance is desired.
DispBegin() and DispEnd() calls are optional. They are not required for normal output.
Notes
■ Nested calls: DispBegin() calls are nested internally. If
several DispBegin() calls occur, buffering is allowed until a corresponding number of DispEnd() calls occur.
■ Guaranteed operations: Display updates performed between
DispBegin() and DispEnd() are not guaranteed to be buffered—some updates may become visible before DispEnd() is called. However, all updates are guaranteed to be visible after the closing call to DispEnd().
■ Terminal operations: Terminal input operations such as Inkey()
or READ should not be performed between DispBegin() and DispEnd(). Doing this may cause input or display output to be lost.
■ Incompatible operations: Display output by other than the
CA-Clipper display functions (e.g., by add-on libraries or by DOS via OutStd(), etc.) may not be compatible with DispBegin() and DispEnd(). Output may be lost.
Examples
■ This example buffers screen output, updates the screen, and
then displays the buffered screen output:
DispBegin() // Start screen buffering
//
SetPos(10, 10)
DispOut("A display update")
SetPos(11, 10)
DispOut("Another display update")
//
DispEnd() // Display buffered screen data
nTop, nLeft, nBottom, and nRight define the coordinates of the box. DispBox() draws a box using row values from zero to MaxRow(), and column values from zero to MaxCol(). If nBottom and nRight are larger than MaxRow() and MaxCol(), the bottom-right corner is drawn off the screen.
cnBoxString is a numeric or character expression that defines the border characters of the box. If specified as a numeric expression, a value of 1 displays a single-line box and a value of 2 displays a double-line box. All other numeric values display a single-line box.
If cnBoxString is a character expression, it specifies the characters to be used in drawing the box. This is a string of eight border characters and a fill character. If cnBoxString is specified as a single character, that character is used to draw the whole box.
If this argument is not specified, a single-line box is drawn.
cColorString defines the display color of the box that is drawn. If not specified, the box is drawn using the standard color setting of the current system color as defined by SetColor().
Returns
DispBox() always returns NIL.
Description
DispBox() is a screen function that draws a box at the specified display coordinates in the specified color. If you specify cnBoxString, DispBox() draws a box on the screen using configurable border and fill characters. DispBox() draws the box using cnBoxString starting from the upper left-hand corner, proceeding clockwise and filling the screen region with the ninth character. If the ninth character is not specified, the screen region within the box is not painted. Existing text and color remain unchanged.
In cases where cnBoxString respects CA-Clipper conventions, the behavior of DispBox() is unchanged. The behavior of this function can easily be modified to take advantage of graphic mode. For example, you can replace the standard window frames using single or double lines with new graphical frames that have an impressive 3-D look. Simply replace the cBoxString parameter using the following:
Chr(2) + Chr(nColor+1) // draws a box of thickness 16x8x16x8 Chr(3) + Chr(nColor+1) // draws a box of thickness 8x8x8x8 Chr(4) + Chr(nColor+1) // draws a box of thickness
// 16x16x16x16
Chr(5) + Chr(nColor+1) // draws a box of thickness 16x8x8x8
Note that nColor is a numeric color representation. You must add 1 to this value.
In general, Chr(2) + Chr(nColor+1) can be used instead of CA-Clipper's B_SINGLE or B_DOUBLE defines.
CA-Clipper graphics comes with two #defines LLG_BOX_GRAY_STD and LLG_BOX_GRAY_SQUARE to allow gray (nColor=7) boxes of width 16x8 or 16x16.
You can completely customize the box by passing Chr(1) + ... as the first parameter:
Chr(1) + ; // Box entirely defined Chr(nBackColor+1) + ; // Color used as background fill Chr(nLightColor+1) + ; // Color used to lighten the frame Chr(nDarkColor+1) + ; // Color used to darken the frame Chr(nWidthUp) + ; // Thickness of upper edge of box Chr(nWidthRight) + ; // Thickness of right edge of box Chr(nWidthDown) + ; // Thickness of lower edge of box Chr(nWidthLeft) // Thickness of left edge of box
After DispBox() executes, the cursor is located in the upper corner of the boxed region at nTop + 1 and nLeft + 1. Row() and Col() are also updated to reflect the new cursor position.
Note that box.ch, located in \CLIP53\INCLUDE, provides constants for various border configurations.
Notes
The number of colors available depends on the current video mode setting ( SET VIDEOMODE ).
Examples
■ This code example displays a double-line box using a numeric
value to specify the box border:
#define B_SINGLE 1
#define B_DOUBLE 2
//
DispBox(1, 1, 10, 10, B_DOUBLE, "BG+/B")
■ This example displays a single-line top and double-line side
box by specifying border characters with a manifest constant defined
in box.ch:
#include "Box.ch"
//
DispBox(1, 1, 10, 10, B_SINGLE_DOUBLE, "BG+/B")
■ This example displays a box with a 3-D look. It can be used
for graphic mode:
// Display a box with a 3D look of constant width 16x16x16x16
DispBox( nTop, nLeft, nBottom, nRight, LLG_BOX_GRAY_SQUARE )
// Write some transparent text in the 3D frame
GWRITEAT( nLeft * GMODE()[LLG_MODE_FONT_COL] ,;
nTop * GMODE()[LLG_MODE_FONT_ROW] ,;
"This is some Text...",;
4,;
LLG_MODE_SET; )
DispCount() returns the number of DispEnd() calls required to restore the original display context.
Description
You can use DispCount() to determine the current display context. CA-Clipper uses display contexts to buffer and to supervise screen output operations.
Each call to DispBegin() defines a new display context. Output to the display context is suppressed until a matching DispEnd() statement executes.
Since you may nest DispBegin() calls, use DispCount() to determine whether there are pending screen refresh requests.
Examples
■ This example saves the setting of DispCount(), then releases
all pending display contexts before writing to the screen:
PROCEDURE ForceDisplay(cExp)
LOCAL nSavCount
nSavCount := DispCount()
// Discard pending display contexts
DO WHILE ( DispCount() > 0)
DispEnd()
ENDDO
DispOut(cExp)
// "Rewind" the current display context
DO WHILE (DISPCCOUNT() < nSavCount )
DispBegin()
ENDDO
RETURN
DispEnd() is a screen function that informs the CA-Clipper display output system that the application has finished performing a series of display operations.
DispEnd() is used with DispBegin() so the display output system can buffer display updates. This can be important for applications in which complex screen displays are slow and the appearance of performance is desired.
Examples
■ This example buffers screen output, updates the screen, and
then displays the buffered screen output:
DispBegin() // Start screen buffering
//
SetPos(10, 10)
DispOut("A display update")
SetPos(11, 10)
DispOut("Another display update")
//
DispEnd() // Display buffered screen data
cColorString is an optional argument that defines the display color of exp. If unspecified, exp is displayed as the standard color of the current system color as defined by SetColor(). cColorString is a character expression containing the standard color setting. You can specify a literal color setting, if you enclose it in quote marks.
Returns
DispOut() always returns NIL.
Description
DispOut() is a simple output function that writes the value of a single expression to the display at the current cursor position. This function ignores the SET DEVICE setting; output always goes to the screen. You can only use this function within a procedure or function.
Examples
■ This example performs screen output at a specified location in
different colors. Note how the cursor position is saved and restored
using Row(), Col(), and SetPos():
PROCEDURE Showit
LOCAL nRow, nCol
? nCol := Col() // save original
?? nRow := Row() // cursor position
Inkey(2)
SetPos(nRow, nCol)
DispOut("This is a test of DispOut()")
? Col() // display current
?? Row() // cursor position
Inkey(2)
SetPos(nRow, nCol)
DispOut(Space(26)) // clear original position
SET DEVICE TO PRINTER // ignores SET DEVICE
SetPos(nRow, nCol) // display at
DispOut(" all through")
// original position
RETURN
xcFileSpec is a template that must be matched by displayed files and can include standard wildcard (* and ?) characters. You can specify xcFileSpec as a literal file specification string or as a character expression enclosed in parentheses.
Description
DIR is a file command that displays a listing of files from the specified path in one of two formats depending on whether you specify the xcFileSpec argument. If you do not specify a path, DIR displays a standard listing of database files from the current or specified directory. The list includes the database file name, date of last update, and number of records. Including the option xcFileSpec displays a list of all files in the specified directory. This list includes the file name, extension, number of bytes, and date of last update.
If no path is specified, DIR displays files from the current DOS drive and directory unless SET DEFAULT has been used to specify a new default directory.
DIR is a compatibility command and therefore not recommended. It is superseded by the Directory() function which returns an array of file information from a wildcard pattern. Using this array, you can display file information to screen.
Notes
■ Directory picklists: To present directory information to the
user, use ADir() to return one or more arrays of directory information, and AChoice() to present a picklist to the user.
Examples
■ These examples display DOS and database files in the current
directory:
cFilespec := "*.*"
DIR (cFilespec) // Display all files
DIR // Display all (.dbf) files
DIR *.prg // Display all program files
exp list is the list of values to display for each record processed.
TO PRINTER echoes output to the printer.
TO FILExcFile echoes output to the indicated file which can be specified either as a literal file name or as a character expression enclosed in parentheses. If an extension is not specified, .txt is added.
scope is the portion of the current database file to DISPLAY. The default is the current record, or NEXT 1. If a condition is specified, the scope becomes ALL.
WHILElCondition specifies the set of records meeting the condition from the current record until the condition fails.
FORlCondition specifies the conditional set of records to DISPLAY within the given scope.
OFF suppresses the display of the record number.
Description
DISPLAY is a database command that sequentially accesses records in the current work area, sending the results of the exp list to the console in a tabular format with each column separated by a space. The command does not display column headers or pause at predetermined intervals. DISPLAY is identical to LIST with the exception that its default scope is NEXT 1 rather than ALL.
When invoked, output is sent to the screen and optionally to the printer and/or a file. To suppress output to the screen while printing or echoing output to a file, SET CONSOLE OFF before the DISPLAY command line.
Notes
■ Interrupting output: To let the user interrupt the processing
of a DISPLAY command, using the Inkey() function, add a test for the interrupt key press to the FOR condition. See the example below.
■ Printer margin: Since DISPLAY is a console command, it honors
the current SET MARGIN for output echoed to the printer.
Examples
■ This example illustrates a simple DISPLAY, and a conditional
DISPLAY to the printer:
USE Sales NEW
DISPLAY Date(), Time(), Branch
DISPLAY Branch, Salesman FOR Amount > 500 TO PRINTER
■ This example interrupts a DISPLAY using Inkey() to test
whether the user pressed the Esc key:
#define K_ESC 27
USE Sales INDEX SalesMan NEW
DISPLAY Branch, Salesman, Amount WHILE ;
Inkey() != K_ESC
nNewOsCode, if specified, alters the value returned by DosError(). The value must be a numeric value that reflects a DOS error number.
Returns
DosError() returns the DOS error number as an integer numeric value.
Description
DosError() is an error function that returns the last DOS error code associated with an activation of the runtime error block. When a runtime error occurs, the DosError() function is set to the current DOS error if the operation has an associated DOS error. The function value is retained until another runtime error occurs. If the failed operation has no associated DOS error, the DosError() returns zero. With low- level file functions, FError() returns the same value as DosError().
Through use of the optional nNewOsCode, you may customize to the reporting activation the returned value for any DOS error.
For a complete list of DOS error numbers and accompanying descriptions, refer to the Error Messages and Appendices Guide.
DoW() returns the day of the week as a number between zero and seven. The first day of the week is one (Sunday) and the last day is seven (Saturday). If dDate is empty, DoW() returns zero.
Description
DoW() is a date conversion function that converts a date value to a number identifying the day of the week. It is useful when you want date calculations on a weekly basis. DoW() is similar to CDoW(), which returns the day of week as a character string instead of a number.
Examples
■ These examples illustrate CDoW() and its relationship to
DoW():
? Date() // Result: 09/01/89
? DoW(Date()) // Result: 3
? CDoW(Date()) // Result: Tuesday
? DoW(Date() - 2) // Result: 1
? CDoW(Date() - 2) // Result: Sunday
■ This is a user-defined function that uses DoW() to calculate
the date of last Monday from any other date:
FUNCTION LastMonday(dDate)
RETURN (dDate - DoW(dDate) + 2)
Execute one of several alternative blocks of statements
Syntax
DO CASE
CASE <lCondition1>
<statements>...
[CASE <lCondition2>]
<statements>...
[OTHERWISE]
<statements>...
END[CASE]
Arguments
CASElCondition defines a block of statements to be executed if lCondition evaluates to true (.T.).
OTHERWISE defines a block of statements to be executed if none of the specified CASE conditions evaluates to true (.T.).
Description
DO CASE...ENDCASE is a control structure that executes one of several blocks of statements depending on which of the associated conditions is true (.T.). It works by branching execution to the statements following the first CASElCondition that evaluates to true (.T.). Execution continues until the next CASE, OTHERWISE, or ENDCASE is encountered. Control then branches to the first statement following the next ENDCASE statement.
If none of the CASE conditions evaluates to true (.T.), the statements following the OTHERWISE statement are executed up to the matching ENDCASE statement. If an OTHERWISE statement is omitted, control branches to the first statement following the matching ENDCASE statement.
You may nest any number of statements, including other control structures (i.e., DO WHILE and FOR), within a single DO CASE structure. In addition, within a single DO CASE structure, there is no fixed limit on the number of CASE statements that a DO CASE structure may contain.
DO CASE...ENDCASE is identical to IF...ELSEIF...ENDIF with neither syntax having a specific advantage over the other.
Examples
■ This example uses DO CASE in a menu structure to branch
control based on user selection:
@ 3, 25 PROMPT "First choice"
@ 4, 25 PROMPT "Second choice"
MENU TO nChoice
//
DO CASE
CASE nChoice = 0
RETURN
CASE nChoice = 1
ChoiceOne()
CASE nChoice = 2
ChoiceTwo()
ENDCASE
[DO] WHILE <lCondition>
<statements>...
[EXIT]
<statements>...
[LOOP]
<statements>...
END[DO]
Arguments
lCondition is the logical control expression for the DO WHILE loop.
EXIT unconditionally branches control from within a DO WHILE or FOR...NEXT structure to the statement immediately following the corresponding ENDDO or NEXT statement.
LOOP branches control to the most recently executed DO WHILE or FOR statement.
Description
DO WHILE...ENDDO is a control structure that executes a block of statements repetitively, as long as lCondition evaluates to true (.T.). When the condition evaluates to true (.T.), control passes into the structure and proceeds until an EXIT, LOOP, or ENDDO is encountered. ENDDO returns control to the DO WHILE statement and the process repeats itself. If an EXIT statement is encountered, control branches to the nearest ENDDO or NEXT statement. If a LOOP statement is encountered, control branches to the nearest DO WHILE or FOR statement. If the condition evaluates to false (.F.), the DO WHILE construct terminates and control passes to the statement immediately following the ENDDO.
Use EXIT to terminate a DO WHILE structure based on a condition other than the DO WHILE condition. LOOP, by contrast, prevents execution of statements within a DO WHILE based on an intermediate condition, and returns to the most recent DO WHILE statement.
DO WHILE constructs may be nested within any other control structures to any depth. The only requirement is that each control structure be properly nested.
Examples
■ This example demonstrates a typical control structure for a
simple grouped report:
LOCAL cOldSalesman, nTotalAmount
USE Sales INDEX Salesman NEW
DO WHILE .NOT. Eof()
cOldSalesman := Sales->Salesman
nTotalAmount := 0
DO WHILE cOldSalesman = Sales->Salesman ;
.AND. (.NOT. Eof())
? Sales->Salesman, Sales->Amount
nTotalAmount := nTotalAmount + Sales->Amount
SKIP
ENDDO
? "Total: ", nTotalAmount, "for", cOldSalesman
ENDDO
CLOSE Sales
■ This code fragment demonstrates how LOOP can be used to
provide an intermediate processing condition:
DO WHILE <lCondition>
<initial processing>...
IF <intermediate condition>
LOOP
ENDIF
<continued processing>...
ENDDO
■ This example demonstrates the use of DO WHILE to emulate a
repeat until looping construct:
LOCAL lMore := .T.
DO WHILE lMore
<statements>...
lMore := (<lCondition>)
ENDDO
■ This example uses a DO WHILE loop to move sequentially through
a database file:
DO WHILE .NOT. Eof()
<statements>...
SKIP
ENDDO
idProcedure is the name of the procedure or user-defined function to be executed.
WITHargument list specifies up to 128 arguments, separated by commas, to pass to idProcedure. Each argument may be a single variable, field, array, array element, expression, or object. Arguments can be skipped or left off the end of the list.
Description
The DO statement calls a procedure or user-defined function, optionally passing arguments to the called routine. It performs the same action as a user-defined function or procedure specified on a line by itself with the exception that variables other than field variables are passed by reference as the default. In order to pass a field variable as an argument, enclose it in parentheses, unless you declare it with the FIELD statement or with an alias.
In CA-Clipper, the number of specified arguments need not match the number of specified parameters in the called procedure. If the number of arguments is less than the number of parameters, the parameter variables with no corresponding arguments are initialized with a NIL value when the procedure is called. If the number of arguments is greater than the number of parameters, they are ignored.
Also, skipping an argument within the argument list by leaving an empty spot next to the comma initializes the corresponding argument to NIL. To detect the position of the last argument passed in the argument list, use PCount(). To detect a skipped argument, compare the receiving parameter to NIL.
In addition to calling a procedure or user-defined function, DO also has an effect on compilation if you compile the current program file without the /M option. If the CA-Clipper compiler encounters a DO statement and the specified procedure has not already been compiled, the compiler searches the current directory for a .prg file with the same name and compiles it. If the file with the same name as the procedure is not found, the called procedure is assumed to be external, and a reference is added to the object (.OBJ) file. At link time, the linker will search other object files and libraries for this external reference.
In CA-Clipper, DO is a compatibility statement and therefore not recommended. Calling a procedure or function on a line by itself is the preferred method. Since this preferred calling convention normally passes parameters by value, you must preface an argument with the pass- by-reference operator (@) in order to pass by reference. If you are using DO to make a procedure call more readable, a user-defined command, specified with the #command directive, can provide greater readability without sacrificing the safety of variables passed as parameters.
For more information on passing parameters refer to the Functions and Procedures section of the "Basic Concepts" chapter in the Programming and Utilities Guide.
Examples
■ This example executes a procedure with no parameters:
DO AcctsRpt
AcctsRpt() // Preferred method
■ This example executes a procedure passing two constants:
DO QtrRpt WITH "2nd", "Sales Division"
QtrRpt("2nd", "Sales Division") // Preferred method
■ In this example, a procedure is executed with the first
argument passed by value and the second passed by reference:
nNumber := 12
DO YearRpt WITH nNumber + 12, nNumber
YearRpt(nNumber + 12, @nNumber) // Preferred method
■ Here, a procedure is invoked with skipped arguments embedded
in the list of arguments:
DO DisplayWindow WITH ,,,,"My Window"
DisplayWindow(,,,,"My Window") // Preferred method
DToC() returns a character string representation of a date value. The return value is formatted in the current date format. The default format is mm/dd/yy. A null date returns a string of spaces equal in length to the current date format.
Description
DToC() is a date conversion function used for formatting purposes when you want to display the date in the SET DATE format and when a character expression is required (in a LABEL FORM, for example). If you need a specialized date format, you can use Transform() or a custom expression.
If you are INDEXing a date in combination with a character string, use DToS() instead of DToC() to convert the date value to a character string.
Examples
■ These examples show general uses of DToC():
? Date() // Result: 09/01/90
? DToC(Date()) // Result: 09/01/90
? "Today is " + DToC(Date())
// Result: Today is 09/01/90
Convert a date value to a character string formatted as yyyymmdd
Syntax
DToS(<dDate>) → cDate
Arguments
dDate is the date value to convert.
Returns
DToS() returns a character string eight characters long in the format yyyymmdd. When dDate is a null date (CToD("")), DToS() returns a string of eight spaces. The return value is not affected by the current date format.
Description
DToS() is a date conversion function that is used when creating index expressions consisting of a date value and a character expression. DToS() converts a date value to a character string that can be concatenated to any other character expression. The return value is structured to preserve date order (year, month, and day).
Examples
■ These examples illustrate DToS() in conjunction with several
other functions:
? Date() // Result: 09/01/90
? DToS(Date()) // Result: 19900901
? Len(DToS(CToD(""))) // Result: 8
■ This example demonstrates how to create an index with a
compound date and character key using DToS():
USE Sales NEW
INDEX ON DToS(Date) + Salesman TO DateName
EJECT is a printing command that sends a formfeed character (Chr(12)) to the printer and sets the PCol() and PRow() values to zero. If you address a printer row less than the last row position since an EJECT or SetPRC() was executed, CA-Clipper automatically performs an EJECT. Because of this, your printing logic must proceed sequentially from left to right down the page. If you need to reset the internal printer row and column values to zero without sending a formfeed, use SetPRC().
Examples
■ This example prints a simple list report and uses EJECT to
advance to a new page when the line counter reaches the maximum
number of lines to print per page:
LOCAL nLine := 99, nPage := 0
USE Sales NEW
SET PRINTER ON
SET CONSOLE OFF
DO WHILE !Eof()
IF nLine > 55
EJECT
? "Page " + LTrim(Str(++nPage, 3))
? "Date " + CToD(Date())
?
? "Salesman", "Amount"
?
nLine := 6
ENDIF
? Sales->Salesman, Sales->Amount
nLine++
SKIP
ENDDO
SET PRINTER OFF
SET CONSOLE ON
CLOSE
Empty() returns true (.T.) if the expression results in an empty value; otherwise, it returns false (.F.). The criteria for determining whether a value is considered empty depends on the data type of exp according to the following rules:
List of Empty Values
Data Type Contents
Array Zero-length
Character Spaces, tabs, CR/LF, or ("")
Numeric 0
Date Null (CToD(""))
Logical False (.F.)
Memo Same as character
NIL NIL
Description
The Empty() function has a number of uses. You can use it to determine if a user entered a value into a Get object before committing changes to a database file. It can also determine whether a formal parameter is NIL or unsupplied. In addition, it can test an array for zero-length.
Notes
■ Space characters: The Empty() function treats carriage
returns, line feeds, and tabs as space characters and removes these as well.
Examples
■ These examples illustrate use of Empty() against several
different data types:
? Empty(Space(5)), Empty("") // Result: .T. .T.
? Empty(0), Empty(CToD("")) // Result: .T. .T.
? Empty(.F.), Empty(NIL) // Result: .T. .T.
■ This example uses Empty() to determine whether the user
entered a value into the first Get object before writing the new
value to the database file:
LOCAL cCust := Space(15), nAmount := 0
USE Sales NEW
@ 10, 10 GET cCust
@ 11, 10 GET nAmount PICTURE "999.99"
READ
//
IF !Empty(cCust)
APPEND BLANK
REPLACE Sales->Cust WITH cCust, Sales->Amount ;
WITH nAmount
ENDIF
■ This example uses Empty() as part of the VALID clause to force
the user to enter data into the current Get object:
LOCAL cCode := Space(5)
@ 2, 5 SAY "Enter code" GET cCode VALID !Empty(cCode)
READ
Eof() returns true (.T.) when an attempt is made to move the record pointer beyond the last logical record in a database file; otherwise, it returns false (.F.). If there is no database file open in the current work area, Eof() returns false (.F.). If the current database file contains no records, Eof() returns true (.T.).
Description
Eof() is a database function used to test for an end of file boundary condition when the record pointer is moving forward through a database file. Any command that can move the record pointer can set Eof().
The most typical application is as a part of the lCondition argument of a DO WHILE construct that sequentially processes records in a database file. Here lCondition would include a test for .NOT.Eof(), forcing the DO WHILE loop to terminate when Eof() returns true (.T.).
Eof() and Found() are often used interchangeably to test whether a SEEK, FIND, or LOCATE command failed. With these commands, however, Found() is preferred.
When Eof() returns true (.T.), the record pointer is positioned at LastRec() + 1 regardless of whether there is an active SET FILTER or SET DELETED is ON. Further attempts to move the record pointer forward return the same result without error. Once Eof() is set to true (.T.), it retains its value until there is another attempt to move the record pointer.
By default, Eof() operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression (see example below).
Examples
■ This example demonstrates Eof() by deliberately moving the
record pointer beyond the last record:
USE Sales
GO BOTTOM
? Eof() // Result: .F.
SKIP
? Eof() // Result: .T.
■ This example uses aliased expressions to query the value of
Eof() in unselected work areas:
USE Sales NEW
USE Customer NEW
? Sales->(Eof())
? Customer->(Eof())
■ This example illustrates how Eof() can be used as part of a
condition for sequential database file operations:
USE Sales INDEX CustNum NEW
DO WHILE !Eof()
nOldCust := Sales->CustNum
nTotalAmount := 0
DO WHILE nOldCust = Sales->CustNum .AND. (!Eof())
? Sales->CustNum, Sales->Description, ;
Sales->SaleAmount
nTotalAmount += Sales->SaleAmount
SKIP
ENDDO
? "Total amount: ", nTotalAmount
ENDDO
Provides objects containing information about runtime errors
Description
An Error object is a simple object that contains information pertaining to a runtime error. Error objects have no methods, only exported instance variables. When a runtime error occurs, CA-Clipper creates a new Error object and passes it as an argument to the error handler block specified with the ErrorBlock() function. Within the error handler, the Error object can then be queried to determine the nature of the error condition.
Error objects can also be returned to the RECOVER statement of a BEGIN SEQUENCE construct with a BREAK statement. Here, the error object can be queried for local error handling. For more detailed information and examples refer to the "Error Handling Strategies" chapter in the Programming and Utilities Guide.
Methods link
Class Function
ErrorNew() Create a new Error object
ErrorNew() → oError
Returns
ErrorNew() returns a new Error object.
Exported Instance Variables
args An array of function or operator arguments
args (Assignable)
Contains an array of the arguments supplied to an operator or function when an argument error occurs. For other types of errors, Error:args contains a NIL value.
canDefault Indicates if default recovery is available
canDefault (Assignable)
Contains a logical value indicating whether the subsystem can perform default error recovery for the error condition. A value of true (.T.) indicates that default recovery is available. Availability of default handling and the actual default recovery strategy depends on the subsystem and the error condition. The minimum action is simply to ignore the error condition.
Default recovery is requested by returning false (.F.) from the error block invoked to handle the error. Note that Error:canDefault is never true (.T.) if Error:canSubstitute is true (.T.).
canRetry Indicates if a retry is possible after an error
canRetry (Assignable)
Contains a logical value indicating whether the subsystem can retry the operation that caused the error condition. A value of true (.T.) indicates that a retry is possible. Retry may or may not be available, depending on the subsystem and the error condition.
Retry is requested by returning true (.T.) from the error block invoked to handle the error. Note that Error:canRetry never contains true (.T.) if Error:canSubstitute contains true (.T.).
canSubstitute Indicates if a new result can be substituted after an error
canSubstitute (Assignable)
Contains a logical value indicating whether a new result can be substituted for the operation that produced the error condition. Argument errors and certain other simple errors allow the error handler to substitute a new result value for the failed operation. A value of true (.T.) means that substitution is possible.
The substitution is performed by returning the new result value from the code block invoked to handle the error. Note that Error:canSubstitute is never true (.T.) if either Error:canDefault or Error:canRetry is true (.T.).
cargo User-definable variable
cargo (Assignable)
Contains a value of any data type unused by the Error system. It is provided as a user-definable slot, allowing arbitrary information to be attached to an Error object and retrieved later.
description Character description of the error condition
description (Assignable)
Contains a character string that describes the error condition. A zero-length string indicates that the subsystem does not provide a printable description for the error. If Error:genCode is not zero, a printable description is always available.
filename Name of the file associated with the error
filename (Assignable)
Contains a character value representing the name originally used to open the file associated with the error condition. A zero-length string indicates either that the error condition is not associated with a particular file or that the subsystem does not retain file name information.
genCode CA-Clipper error code number
genCode (Assignable)
Contains an integer numeric value representing a CA-Clipper generic error code. Generic error codes allow default handling of similar errors from different subsystems. A value of zero indicates that the error condition is specific to the subsystem and does not correspond to any of the generic error codes. The header file, error.ch, provides a set of manifest constants for generic error codes.
operation Character description of the failed operation
operation (Assignable)
Contains a character string that describes the operation being attempted when the error occurred. For operators and functions, Error:operation contains the name of the operator or function. For undefined variables or functions, it contains the name of the variable or function. A zero-length string indicates that the subsystem does not provide a printable description of the operation.
osCode Operating system error code number
osCode (Assignable)
Contains an integer numeric value representing the operating system error code associated with the error condition. A value of zero indicates that the error condition was not caused by an error from the operating system. When Error:osCode is set to a value other than zero, DosError() is updated with the same value.
Error:osCode properly reflects the DOS extended error code for file errors. This allows proper distinction between errors which result from sharing violations (e.g., opening EXCLUSIVE when another process has already opened the file) and access violations (e.g., opening read/write when the file is marked read-only).
For a list of DOS error codes refer to the Error Messages and Appendices Guide.
severity Indicates error severity
severity (Assignable)
Contains a numeric value indicating the severity of the error condition. Four standard values are defined in error.ch:
Error:severity Values
Error.ch Meaning
ES_WHOCARES The condition does not represent a failure; the
error is informational.
ES_WARNING The condition does not prevent further
operations, but may result in a more serious
error later.
ES_ERROR The condition prevents further operations without
corrective action of some kind.
ES_CATASTROPHIC The condition requires immediate termination of
the application.
Note that the CA-Clipper runtime support code only generates errors with severities of ES_WARNING or ES_ERROR.
subCode Subsystem-specific error code number
subCode (Assignable)
Contains an integer numeric value representing a subsystem-specific error code. A value of zero indicates that the subsystem does not assign any particular number to the error condition.
subSystem Character description of the subsystem generating the error
subSystem (Assignable)
Contains a character string representing the name of the subsystem generating the error. For errors with basic CA-Clipper operators and functions, the subsystem name "BASE" is given. For errors generated by a database driver, Error:subSystem contains the name of the database driver.
tries Number of times the failed operation has been attempted
tries (Assignable)
Contains an integer numeric value representing the number of times the failed operation has been attempted. When Error:canRetry is true (.T.), Error:tries can be used to limit the number of retry attempts. A value of zero indicates that the subsystem does not track the number of times the operation has been tried.
Examples
■ This example demonstrates how a file open operation might be
handled in an error handler replicating the default CA-Clipper
behavior. When, for example, an attempt to open a database file with
a USE command fails, control returns to the statement following the
offending command:
#include "Error.ch"
#command RETRY => RETURN (.T.) // Retry operation
#command RESUME => RETURN (.F.) // Default recovery
//
FUNCTION MyError( <oError> )
//
// Handle file open error
IF <oError>:genCode == EG_OPEN .AND.;
<oError>:canDefault .AND.;
NetErr()
//
RESUME
ENDIF
.
. <other error statements>
.
RETURN NIL
■ This example retries an operation within an error handler a
specified number of times:
#include "Error.ch"
#command RETRY => RETURN (.T.) // Retry operation
#command RESUME => RETURN (.F.) // Default recovery
//
FUNCTION MyError( <oError> )
//
// Handle printer not ready error
IF <oError>:genCode == EG_PRINT .AND.;
<oError>:canRetry .AND.;
<oError>:tries < 25
//
RETRY
ENDIF
.
. <other error statements>
.
RETURN NIL
■ This code fragment returns an error object from an error
handler to the RECOVER statement for further processing:
LOCAL objLocal, bLastHandler
//
// Save current and set new error handler
bLastHandler := ErrorBlock({ |oErr| ;
MyHandler(oErr, .T.)})
//
BEGIN SEQUENCE
.
. <operation that might fail>
.
RECOVER USING objLocal
.
. <send messages to objLocal and handle the error>
.
END
//
// Restore previous error handler
ErrorBlock( bLastHandler )
FUNCTION MyHandler( <oError>, lLocalHandler )
//
// Handle locally returning the error object
IF lLocalHandler
BREAK <oError>
ENDIF
.
. <other statements to handle the error>
.
RETURN NIL
Platforms
Available on MS-DOS
File
Header file is error.ch, default error handler is in Errorsys.prg.
bErrorHandler is the code block to execute whenever a runtime error occurs. When evaluated, the bErrorHandler is passed an error object as an argument by the system.
Returns
ErrorBlock() returns the current error handling code block. If no error handling block has been posted since the program was invoked, ErrorBlock() returns the default error handling block.
Description
ErrorBlock() is an error function that defines an error handler to execute whenever a runtime error occurs. Specify the error handler as a code block with the following form,
{ |oError| expression list,... }
where oError is an error object containing information about the error. Within the code block, messages can be sent to the error object to obtain information about the error. Returning true (.T.) from the error handling block retries the failed operation and false (.F.) resumes processing.
The error handling code block can be specified either as a list of expressions or as a call to a user-defined function. A call to a user- defined function is more useful since you can use CA-Clipper control statements instead of expressions. This is particularly the case if there is a BEGIN SEQUENCE pending and you want to BREAK to the nearest RECOVER statement.
As this implies, error handling blocks can be used in combination with BEGIN SEQUENCE...END control structures. Within an error handling block, you handle device, low-level, and common errors that have a general recovery mechanism. If the operation needs specific error handling, define a BEGIN SEQUENCE then BREAK to the RECOVER statement, returning the error object for local processing. See the example below.
If no bErrorHandler has been specified using ErrorBlock() and a runtime error occurs, the default error handling block is evaluated. This error handler displays a descriptive message to the screen, sets the ErrorLevel() to 1, then QUITs the program.
Since ErrorBlock() returns the current error handling block, it is possible to specify an error handling block for an operation saving the current error handling block, then restore it after the operation has completed. Also, error handlers specified as code blocks, can be passed to procedures and user-defined functions, and RETURNed as values.
For more information on the structure and operations of error objects, refer to the Error class entry in this chapter and the "Error Handling Strategies" chapter in the Programming and Utilities Guide.
Examples
■ This code fragment posts, and then calls an error handling
block when there is an error within a BEGIN SEQUENCE construct:
LOCAL bErrorHandler, bLastHandler, objErr
bErrorHandler := { |oError| ;
MyErrorHandler(oError) }
//
// Save current handler
bLastHandler := ErrorBlock(bErrorHandler)
//
BEGIN SEQUENCE
.
. <operation statements>
.
// Receive error object from BREAK
RECOVER USING oErrorInfo
.
. <recovery statements>
.
END
ErrorBlock(bLastHandler) // Restore handler
RETURN
FUNCTION MyErrorHandler( oError )
//
BREAK oError // Return error object to RECOVER
RETURN NIL
nNewReturnCode is the new return code setting. This can be a value between zero and 255. The default value at startup is zero. If not specified, ErrorLevel() reports the current setting without assigning a new value.
Returns
ErrorLevel() returns the current CA-Clipper exit code as a numeric value, if one has been set using ErrorLevel() with an argument; otherwise, it returns zero.
Description
ErrorLevel() is a dual purpose environment function. It returns the current CA-Clipper return code and optionally sets a new return code. The return code is a value set by a child process so the parent process can test the termination state of the child process. Typically, the parent process is DOS and the child process is an application program. Retrieve a return code with the DOS ERRORLEVEL command or INT 21 Function 4Dh.
When a CA-Clipper program terminates, the return code is set to 1 if the process ends with a fatal error. If the process ends normally, the return code is set to zero, or the last ErrorLevel() set in the program.
Typically, you would set a return code with ErrorLevel() to indicate an error state to the program that invoked the current CA-Clipper program. In most cases this is the application batch file. Here you would test the return code using the DOS ERRORLEVEL command. Refer to your DOS manual for more information.
Notes
■ ErrorLevel() is not updated after a RUN command terminates.
To obtain the return code of the invoked program, you must create an assembler or C routine that queries the child process return code using INT 21 Function 4Dh. Refer to your DOS documentation for more information.
Examples
■ This example saves the current CA-Clipper return code, then
sets a new value:
nOldCode := ErrorLevel() // Get current error level
ErrorLevel(1) // Set new error level
■ This example uses ErrorLevel() to set a return code that can
be tested by the parent process:
#define ERR_FILE_MISSING 255
#define ERR_POST_INCOMPLETE 254
//
IF !FILE("Sysfile.dbf")
@ 0, 0
@ 1, 0
@ 0, 0 SAY "Fatal error: System ;
file is missing...quitting"
ErrorLevel(ERR_FILE_MISSING)
QUIT
ENDIF
xcFile is the name of the file to be deleted from disk and can be specified either as a literal file name or as a character expression enclosed in parentheses. The file name must be fully specified including the extension, and it may optionally be preceded by a drive and/or path specification.
Description
ERASE is a file command that removes a specified file from disk. SET DEFAULT and SET PATH do not affect ERASE. The file is deleted from disk only if found in the current DOS directory or in the directory explicitly specified as part of the file name.
Warning! Files must be CLOSEd before being ERASEd. Otherwise, either a sharing violation or a date corruption on the drive may occur.
Examples
■ This example removes a specified file from disk and then tests
to see if the file was in fact removed:
? FILE("Temp.dbf") // Result: .T.
ERASE Temp.dbf
? FILE("Temp.dbf") // Result: .F.
BlockArg list is a list of arguments to send to the code block before it is evaluated.
Returns
Eval() returns the value of the last expression within the block. A code block can return a value of any type.
Description
Eval() is a code block function. It is the most basic code block evaluation facility in the CA-Clipper system. A code block is a special data value that refers to a piece of compiled program code. For more information on code blocks, refer to the "Basic Concepts" chapter in the Programming and Utilities Guide.
To execute or evaluate a code block, call Eval() with the block value and any parameters. The parameters are supplied to the block when it is executed. Code blocks may be a series of expressions separated by commas. When a code block is evaluated, the returned value is the value of the last expression in the block.
The CA-Clipper compiler usually compiles a code block at compile time. There are, however, occasions at runtime when you may need to compile a code block from a character string. You can do this by using the macro operator (&).
Eval() is often used to create iteration functions. These are functions that apply a block to each member of a data structure. AEval(), ASort(), AScan(), and dbEval() are iteration functions (e.g., AEval() applies a block to each element within an array).
Examples
■ This example creates a code block that increments a number,
and then evaluates it:
bBlock := { |nArg| nArg + 1 }
? Eval(bBlock, 1) // Result: 2
■ This example demonstrates compiling a code block at runtime
using the macro operator (&):
// Compile a string to a block
bBlock := &("{ |nArg| nArg + 1 }")
// Evaluate the block
? Eval(bBlock, 1) // Result: 2
nExponent is the natural logarithm for which a numeric value is to be calculated.
Returns
Exp() returns a numeric value that is equivalent to the value e raised to the specified power.
Description
Exp() is a mathematical function that calculates the value, y, (the antilogarithm) of the following equation,
e**x = y
where e is the base of natural logarithms (2.71828...) and x is nExponent. The maximum value of nExponent is 45 before a numeric overflow occurs. Exp() and Log() are inverse functions.
The number of decimal places displayed is determined solely by SET DECIMALS regardless of the current SET FIXED value.
Examples
■ This example demonstrates several invocations of Exp():
? Exp(1) // Result: 2.72
SET DECIMALS TO 10
? Exp(1) // Result: 2.7182818285
? Log(Exp(1)) // Result: 1.0000000000
EXIT PROCEDURE declares a procedure that will be executed on program termination.
idProcedure is the name of the exit procedure to declare. Exit procedure names can be any length, but only the first 10 characters are significant. Names may not begin with an underscore but can contain any combination of characters, numbers, or underscores.
FIELD declares a list of identifiers to use as field names whenever encountered. If the IN clause is specified, referring to the declared name includes an implicit reference to the specified alias.
LOCAL declares and optionally initializes a list of variables or arrays whose visibility and lifetime is the current procedure.
MEMVAR declares a list of identifiers to use as private or public memory variables or arrays whenever encountered.
RETURN passes control to the next exit procedure or to the operating system, if no other exit procedures are pending.
Description
The EXIT PROCEDURE statement declares a procedure that will be executed upon program termination. EXIT procedures are called after the last executable statement in a CA-Clipper application has completed. EXIT PROCEDUREs can be used to perform common housekeeping tasks such as saving configuration settings to a file, closing a log file, or concluding a communications session.
The visibility of exit procedures is restricted to the system; therefore, it is not possible to call an EXIT PROCEDURE from a procedure or user-defined function. Exit procedures do not receive parameters.
Once the last executable statement has completed, control passes from one EXIT PROCEDURE to the next until all procedures in the exit list have been called. Control then passes to the operating system.
The ANNOUNCE statement declares a module identifier for a source (.prg) file. Once declared, EXIT PROCEDUREs are referenced with this module identifier. An application may use any number of exit procedures by explicitly REQUESTing their module identifiers.
The EXIT PROCEDUREs requested for an application are collectively referred to as the exit list. There is no mandatory execution order of procedures in the exit list; however, if an EXIT PROCEDURE is declared in the same source (.prg) file as the application's primary routine (root), it is guaranteed to be the first exit procedure called.
Termination of a given CA-Clipper application can be attributed to any of the following:
■ RETURNing from the primary (root) routine
■ the QUIT command
■ issuing a BREAK without an enclosing BEGIN SEQUENCE...END
■ unrecoverable error
Execution of an EXIT PROCEDURE cannot be guaranteed when the system encounters an unrecoverable error. If an error is raised during an exit procedure, the system returns to DOS. Pending exit procedures are not called.
Examples
■ This example illustrates construction of a simple timing
mechanism using INIT and EXIT PROCEDUREs:
// prints the amount of time required to read,
// sort, and display a list of file names.
ANNOUNCE MySystem
STATIC nStart
PROCEDURE Main()
AEval( ASort( Directory( "*.*" ) ),;
{ | aFileInfo | QOut( aFileInfo[ 1 ] ) } )
RETURN
INIT PROCEDURE MyInit()
nStart := Seconds()
RETURN
EXIT PROCEDURE MyExit()
?
? "Elapsed Time: "
?? Seconds() - nStart
RETURN
Declare a list of procedure or user-defined function names to the linker
Syntax
EXTERNAL <idProcedure list>
Arguments
idProcedure list is the list of procedures, user-defined functions, or format procedures to add to the list of routines that will be linked into the current executable (.EXE) file.
Description
EXTERNAL is a declaration statement that specifies uncoded references to the linker. Like all other declaration statements, an EXTERNAL statement must be specified before any executable statements in either the program file, or a procedure or user-defined function definition.
During the compilation of CA-Clipper source code, all explicit references to procedures and user-defined functions are made to the linker. In some instances, there may be no references made to procedure or user-defined function names until runtime. EXTERNAL resolves this by forcing the named procedures or user-defined functions to be linked even if they are not explicitly referenced in the source file. This is important in several instances:
■ Procedures, user-defined functions, or formats referenced with
macro expressions or variables
■ Procedures and user-defined functions used in REPORT and LABEL
FORMs and not referenced in the source code
■ User-defined functions used in index keys and not referenced
To group common EXTERNAL declarations together, place them in a header file and then include (#include) the header file into each program (.prg) file that might indirectly use them.
EXTERNAL is a compatibility statement and therefore not recommended. It is superseded by the REQUEST statement that defines a list of module identifiers to the linker.
Examples
■ These examples are equivalent header files consisting of
common EXTERNAL references for REPORT FORMs:
// Externals.ch
EXTERNAL HardCR
EXTERNAL Tone
EXTERNAL MemoTran
EXTERNAL StrTran
// Externals.ch
EXTERNAL HardCR, TONE, MEMOTRAN, STRTRAN
Close an open binary file and write DOS buffers to disk
Syntax
FClose(<nHandle>) → lError
Arguments
nHandle is the file handle obtained previously from FOpen() or FCreate().
Returns
FClose() returns false (.F.) if an error occurs while writing; otherwise, it returns true (.T.).
Description
FClose() is a low-level file function that closes binary files and forces the associated DOS buffers to be written to disk. If the operation fails, FClose() returns false (.F.). FError() can then be used to determine the reason for the failure. For example, attempting to use FClose() with an invalid handle returns false (.F.), and FError() returns DOS error 6, invalid handle. See FError() for a complete list of error numbers.
Warning! This function allows low-level access to DOS files and devices. It should be used with extreme care and requires a thorough knowledge of the operating system.
Examples
■ This example uses FClose() to close a newly created binary
file and displays an error message if the close fails:
#include "Fileio.ch"
//
nHandle := FCreate("Testfile", FC_NORMAL)
IF !FClose(nHandle)
? "Error closing file, error number: ", FError()
ENDIF
Return the number of fields in the current .dbf file
Syntax
FCount() → nFields
Returns
FCount() returns the number of fields in the database file in the current work area as an integer numeric value. If there is no database file open, FCount() returns zero.
Description
FCount() is a database function. It is useful in applications containing data-independent programs that can operate on any database file. These include generalized import/export and reporting programs. Typically, you use FCount() to establish the upper limit of a FOR...NEXT or DO WHILE loop that processes a single field at a time.
By default, FCount() operates on the currently selected work area.
Examples
■ This example illustrates FCount(), returning the number of
fields in the current and an unselected work area:
USE Sales NEW
USE Customer NEW
? FCount() // Result: 5
? Sales->(FCount()) // Result: 8
■ This example uses FCount() to DECLARE an array with field
information:
LOCAL aFields := Array(FCount())
AFields(aFields)
■ This example uses FCount() as the upper boundary of a FOR loop
that processes the list of current work area fields:
LOCAL nField
USE Sales NEW
FOR nField := 1 TO FCount()
? Field(nField)
NEXT
Create and/or truncate a binary file to zero-length
Syntax
FCreate(<cFile>, [<nAttribute>]) → nHandle
Arguments
cFile is the name of the file to create. If the file already exists, its length is truncated to zero without warning.
nAttribute is one of the binary file attributes shown in the table below. If this argument is omitted, the default value is zero.
Binary File Attributes
Value Fileio.ch Attribute Description
0 FC_NORMAL Normal Create normal read/write file (default)
1 FC_READONLY Read-only Create read-only file
2 FC_HIDDEN Hidden Create hidden file
4 FC_SYSTEM System Create system file
Returns
FCreate() returns the DOS file handle number of the new binary file in the range of zero to 65,535. If an error occurs, FCreate() returns -1 and FError() is set to indicate an error code.
Description
FCreate() is a low-level file function that either creates a new file or opens and truncates an existing file. If cFile does not exist, it is created and opened for writing. If it does exist and can be opened for writing, it is truncated to zero-length. If it cannot be opened for writing, FCreate() returns -1 and FError() returns the appropriate error value.
When FCreate() successfully creates a new file, the file is left open in compatibility sharing mode and read/write access mode. The file attribute specified by the nAttribute argument is applied to the new file when it is closed, allowing writing to a newly created read-only file. For a list of access modes, see FOpen().
Since a file handle is required in order to identify an open file to other file functions, always assign the return value from FCreate() to a variable for later use.
Like other file functions, FCreate() does not use either the DEFAULT or PATH settings for its operation. Instead, it writes to the current DOS directory unless a path is explicitly stated.
Warning! This function allows low-level access to DOS files and devices. It should be used with extreme care and requires a thorough knowledge of the operating system.
Examples
■ This example creates a file called Testfile and opens it for
reading and writing:
#include "Fileio.ch"
//
IF (nHandle := FCreate("Testfile", FC_NORMAL)) == -1
? "File cannot be created:", FError()
BREAK
ELSE
FWrite(nHandle, "Hello there")
FClose(nHandle)
ENDIF
cFile is the name of the file to be deleted from disk, including extension, optionally preceded by a drive and/or path specification.
Returns
FErase() returns -1 if the operation fails and zero if it succeeds. In the case of a failure, FError() can be used to determine the nature of the error.
Description
FErase() is a file function that deletes a specified file from disk. FErase() is the same as the ERASE command but returns a value and can be specified within an expression. When FErase() is called, cFile is deleted from disk only if found in the current DOS directory or in the directory explicitly specified as part of the file name. Like the other file functions and commands, FErase() does not use either SET DEFAULT or SET PATH to locate cFile.
Warning! Files must be CLOSEd before removing them with FErase().
Examples
■ This example deletes a set of files matching a wildcard
pattern:
#include "Directry.ch"
AEval(Directory("*.BAK"), { |aFile| ;
FErase(aFile[F_NAME]) })
■ This example erases a file and displays a message if the
operation fails:
IF FErase("AFile.txt") == -1
? "File erase error:", FError()
BREAK
ENDIF
FError() returns the DOS error from the last file operation as an integer numeric value. If there is no error, FError() returns zero.
FError() Return Values
Error Meaning
0 Successful
2 File not found
3 Path not found
4 Too many files open
5 Access denied
6 Invalid handle
8 Insufficient memory
15 Invalid drive specified
19 Attempted to write to a write-protected disk
21 Drive not ready
23 Data CRC error
29 Write fault
30 Read fault
32 Sharing violation
33 Lock Violation
Description
FError() is a low-level file function that indicates a DOS error after a file function is used. These functions include FClose(), FCreate(), FErase(), FOpen(), FRead(), FReadStr(), and FRename(). FError() retains its value until the next execution of a file function.
Warning! This function allows low-level access to DOS files and devices. It should be used with extreme care and requires a thorough knowledge of the operating system.
Examples
■ This example tests FError() after the creation of a binary
file and displays an error message if the create fails:
#include "Fileio.ch"
//
nHandle := FCreate("Temp.txt", FC_NORMAL)
IF FError() != 0
? "Cannot create file, DOS error ", FError()
ENDIF
cFieldName is the name of the field to which the set-get block will refer.
Returns
FieldBlock() returns a code block that, when evaluated, sets (assigns) or gets (retrieves) the value of the given field. If cFieldName does not exist in the specified work area, FieldBlock() returns an empty block.
Description
FieldBlock() is a database function that builds a code block. When executed with an argument, the code block created by this function assigns the value of the argument to cFieldName. When executed without an argument, the code block retrieves the value of cFieldName.
Note that the specified field variable may not exist when the code block is created, but must exist before the code block is executed.
Notes
■ Work area: The code block returned by FieldBlock() sets or
gets the value of the specified field in whatever work area is current when the block is run. For example, given work areas 1 and 2, both containing field FName:
The function FieldWBlock() provides a set-get block for a field in a specific work area.
Examples
■ This example compares FieldBlock() to a code block created
using the macro operator. Note that using FieldBlock() avoids the
speed and size overhead of the macro operator:
// Set-Get block defined using macro operator
bSetGet := &( "{ |setVal| IF( setVal == NIL,;
FName, FName := setVal ) }" )
// Set-Get block defined using FieldBlock()
// bSetGet created here is the functional
// equivalent of bSetGet above
bSetGet := FieldBlock("FName")
Retrieve the value of a field using the ordinal position of the field in the database structure
Syntax
FieldGet(<nField>) → ValueField
Arguments
nField is the ordinal position of the field in the record structure for the current work area.
Returns
FieldGet() returns the value of the specified field. If nField does not correspond to the position of any field in the current database file, FieldGet() returns NIL.
Description
FieldGet() is a database function that retrieves the value of a field using its position within the database file structure rather than its field name. Within generic database service functions this allows, among other things the retrieval of field values without use of the macro operator.
Examples
■ This example compares FieldGet() to functionally equivalent
code that uses the macro operator to retrieve the value of a field:
LOCAL nField := 1, FName, FVal
USE Customer NEW
//
// Using macro operator
FName := Field( nField ) // Get field name
FVal := &FName // Get field value
// Using FieldGet()
FVal := FieldGet( nField ) // Get field value
Return a field name from the current database (.dbf) file
Syntax
FIELDNAME/Field(<nPosition>) → cFieldName
Arguments
nPosition is the position of a field in the database file structure.
Returns
FieldName() returns the name of the specified field as a character string. If nPosition does not correspond to an existing field in the current database file or if no database file is open in the current work area, FieldName() returns a null string ("").
Description
FieldName() is a database function that returns a field name using an index to the position of the field name in the database structure. Use it in data-independent applications where the field name is unknown. If information for more than one field is required, use AFields() to create an array of field information or COPY STRUCTURE EXTENDED to create a database of field information.
If you need additional database file structure information, use Type() and Len(). To obtain the number of decimal places for a numeric field, use the following expression:
Len(SubStr(Str(idField), RAt(".", ;
Str(idField)) + 1))
By default, FieldName() operates on the currently selected work area as shown in the example below.
Examples
■ These examples illustrate FieldName() used with several other
functions:
USE Sales
? FieldName(1) // Result: BRANCH
? FCount() // Result: 5
? Len(FieldName(0)) // Result: 0
? Len(FieldName(40)) // Result: 0
■ This example uses FieldName() to list the name and type of
each field in Customer.dbf:
USE Customer NEW
FOR nField := 1 TO FCount()
? PadR(FieldName(nField), 10),;
ValType(&(FieldName(nField)))
NEXT
■ This example accesses fields in unselected work areas using
aliased expressions:
USE Sales NEW
USE Customer NEW
USE Invoices NEW
//
? Sales->(FieldName(1)) // Result: SALENUM
? Customer->(FieldName(1)) // Result: CUSTNUM
cFieldName is the name of a field in the current or specified work area.
Returns
FieldPos() returns the position of the specified field within the list of fields associated with the current or specified work area. If the current work area has no field with the specified name, FieldPos() returns zero.
Description
FieldPos() is a database function that is the inverse of the FieldName() function. FieldPos() is most often used with the FieldPut() and FieldGet() functions.
FieldPos() return the names of fields in any unselected work area by referring to the function using an aliased expression. See the example below.
Examples
■ This example demonstrates a typical specification of the
FieldPos() function:
USE Customer NEW
? FieldPos("Name") // Result: 1
? FieldGet(FieldPos("Name")) // Result: Kate
■ This example uses FieldPos() to return the position of a
specified field in a unselected work area:
USE Customer NEW
USE Invoices NEW
? Customer->(FieldPos("Name")) // Result: 1
? Customer->(FieldGet(FieldPos("Name")))
// Result: Kate
Set the value of a field variable using the ordinal position of the field in the database structure
Syntax
FieldPut(<nField>, <expAssign>) → ValueAssigned
Arguments
nField is the ordinal position of the field in the current database file.
expAssign is the value to assign to the given field. The data type of this expression must match the data type of the designated field variable.
Returns
FieldPut() returns the value assigned to the designated field. If nField does not correspond to the position of any field in the current database file, FieldPut() returns NIL.
Description
FieldPut() is a database function that assigns expAssign to the field at ordinal position nField in the current work area. This function allows you to set the value of a field using its position within the database file structure rather than its field name. Within generic database service functions this allows, among other things, the setting of field values without use of the macro operator.
Examples
■ This example compares FieldPut() to functionally equivalent
code that uses the macro operator to set the value of a field:
// Using macro operator
FName := Field(nField) // Get field name
FIELD->&FName := FVal // Set field value
// Using FieldPut()
FieldPut(nField, FVal) // Set field value
cFieldName is the name of the field specified as a character string.
nWorkArea is the work area number where the field resides specified as a numeric value.
Returns
FieldWBlock() returns a code block that, when evaluated, sets (assigns) or gets (retrieves) the value of cFieldName in the work area designated by nWorkArea. If cFieldName does not exist in the specified work area, FieldWBlock() returns an empty block.
Description
FieldWBlock() is a database function that builds a code block. When evaluated with the Eval() function, the code block first selects the designated nWorkArea. If an argument was passed, the code block then assigns the value of the argument to cFieldName. If no argument was passed, the code block retrieves the value of cFieldName. The original work area is then reselected before the code block returns control.
Note that the specified field variable may not exist when the code block is created but must exist before the code block is executed.
Notes
■ FieldWBlock() is similar to FieldBlock(), except that
FieldBlock() incorporates a fixed work area into the set-get block.
Examples
■ This example compares FieldWBlock() to a code block created
using the macro operator. Note that using FieldWBlock() avoids the
speed and size overhead of the macro operator:
// Set-Get block for work area 1 defined with
// macro operator
bSetGet := &( "{ |setVal| IF( setVal == NIL, ;
1->FName, 1->FName := setVal ) }" )
// Set-Get block defined using FieldWBlock()
// bSetGet created here is the functional
// equivalent of bSetGet above
bSetGet := FieldWBlock("FName", 1)
idField list is a list of names to declare as fields to the compiler.
IN idAlias specifies an alias to assume when there are unaliased references to the names specified in the idField list. Unaliased references to variables in idField list are treated as if they are preceded by the special field alias (FIELD->).
Description
The FIELD statement declares the names of database fields to the compiler, and optionally supplies an implicit alias for each name. This allows the compiler to resolve references to variables with no explicit alias—by implicitly assuming the specified idAlias. Only explicit, unaliased references to the specified fields in the idField list are affected. The FIELD statement, like all declarations, has no effect on references made within macro expressions or variables.
The FIELD statement neither opens a database file nor verifies the existence of the specified fields. It is useful primarily to ensure correct references to fields whose accessibility is known at runtime. Attempting to access the fields when the associated database is not in USE will cause an error.
The scope of the FIELD declaration is the procedure or function in which it occurs, or the entire program (.prg) file if the declaration precedes all PROCEDURE or FUNCTION declarations and the /N compiler option is specified.
FIELD statements, like other declarations, must precede any executable statements in the procedure or function definition or the program (.prg) file if the declaration has filewide scope.
FIELD used with the /W compiler option performs compile-time checking for undeclared variables.
For more information on variable declarations and scoping, refer to the Variables section in the "Basic Concepts" chapter of the Programming and Utilities Guide.
Examples
■ This user-defined function includes statements to declare
database field names in both the current and Employee work areas:
FUNCTION DisplayRecord
FIELD CustNo, OrderNo, Salesman
FIELD EmpName, EmpCode IN Employee
USE Employee NEW
USE Orders NEW
//
? CustNo // Refers to Orders->CustNo
? EmpName // Refers to Employee->EmpName
//
CLOSE Orders
CLOSE Employee
RETURN NIL
Determine if files exist in the CA-Clipper default directory or path
Syntax
FILE(<cFilespec>) → lExists
Arguments
cFilespec is in the current CA-Clipper default directory and path. It is a standard file specification that can include the wildcard characters * and ? as well as a drive and path reference. Explicit references to a file must also include an extension.
Returns
File() returns true (.T.) if there is a match for any file matching the cFilespec pattern; otherwise, it returns false (.F.).
Description
File() is an environment function that determines whether any file matching a file specification pattern is found. File() searches the specified directory if a path is explicitly specified.
If a path is not specified, File() searches the current CA-Clipper default directory and then the CA-Clipper path. In no case is the DOS path searched. Note also that File() does not recognize hidden or system files in its search.
Examples
■ In this example FILE() attempts to find Sales.dbf in other
than the current CA-Clipper default:
? FILE("Sales.dbf") // Result: .F.
? FILE("\APPS\DBF\Sales.dbf") // Result: .T.
//
SET PATH TO \APPS\DBF
? FILE("Sales.dbf") // Result: .T.
//
SET PATH TO
SET DEFAULT TO \APPS\DBF\
? FILE("Sales.dbf") // Result: .T.
? FILE("*.dbf") // Result: .T.
xcSearchString is part or all of the index key of a record to search for, and can be specified either as a literal string or as a character expression enclosed in parentheses. If an expression is specified instead of a literal string, FIND operates the same as SEEK.
Description
FIND is a database command that searches an index for the first key matching the specified character string and positions the record pointer to the corresponding record.
If SOFTSEEK is OFF and FIND does not find a record, the record pointer is positioned to LastRec() + 1, Eof() returns true (.T.), and Found() returns false (.F.).
If SOFTSEEK is ON, the record pointer is positioned to the record with the first key value greater than the search argument and Found() returns false (.F.). In this case, Eof() returns true (.T.) only if there are no keys in the index greater than the search argument.
FIND is a compatibility command and therefore not recommended. Its usage is superseded entirely by the SEEK command.
Examples
■ These examples show simple FIND results:
USE Sales INDEX Branch NEW
FIND ("500")
? Found(), Eof(), RecNo() // Result: .F. .T. 85
FIND "200"
? Found(), Eof(), RecNo() // Result: .T. .F. 5
FIND "100"
? Found(), Eof(), RecNo() // Result: .T. .F. 1
FKLabel() returns a character string representing the name of the function key specified by the numeric argument, nFunctionKey. If this argument is less than one or greater than 40, the function returns a null ("") string.
Description
FKLabel() is a compatibility function used to replicate the FKLabel() function in dBASE III PLUS. As a general principle, the use of this function is not recommended and not needed in CA-Clipper. The function keys are labeled Fn, where n ranges from one to 40 and corresponds directly to the FKLabel() argument.
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/FKLABEL.PRG.
FKMax() is a compatibility function used to replicate the FKMax() function in dBASE III PLUS. As a general principle, the use of this function is not recommended and not needed in CA-Clipper. It simply returns a constant value of 40.
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/FKMAX.PRG.
FLock() returns true (.T.) if an attempt to lock a database file in USE in the current work area succeeds; otherwise, it returns false (.F.). For more information on file locking, refer to the "Network Programming" chapter in the Programming and Utilities Guide.
Description
FLock() is a database function used in network environments to lock an open and shared database file, preventing other users from updating the file until the lock is released. Records in the locked file are accessible for read-only operations.
FLock() is related to USE...EXCLUSIVE and RLock(). USE...EXCLUSIVE opens a database file so that no other user can open the same file at the same time and is the most restrictive locking mechanism in CA-Clipper. RLock() is the least restrictive and attempts to place an update lock on a shared record, precluding other users from updating the current record. FLock() falls in the middle.
FLock() is used for operations that access the entire database file. Typically, these are commands that update the file with a scope or a condition such as DELETE or REPLACE ALL. The following is a list of such commands:
Commands that require an FLock()
Command Mode
APPEND FROM FLock() or USE...EXCLUSIVE
DELETE (multiple records) FLock() or USE...EXCLUSIVE
RECALL (multiple records) FLock() or USE...EXCLUSIVE
REPLACE (multiple records) FLock() or USE...EXCLUSIVE
UPDATE ON FLock() or USE...EXCLUSIVE
For each invocation of FLock(), there is one attempt to lock the database file, and the result is returned as a logical value. A file lock fails if another user currently has a file or record lock for the same database file or EXCLUSIVE USE of the database file. If FLock() is successful, the file lock remains in place until you UNLOCK, CLOSE the DATABASE, or RLock().
By default, FLock() operates on the currently selected work area as shown in the example below.
Notes
■ SET RELATION: CA-Clipper does not automatically lock all work
areas in the relation chain when you lock the current work area, and an UNLOCK has no effect on related work areas.
Examples
■ This example uses FLock() for a batch update of prices in
Inventory.dbf:
USE Inventory NEW
IF FLock()
REPLACE ALL Inventory->Price WITH ;
Inventory->Price * 1.1
ELSE
? "File not available"
ENDIF
■ This example uses an aliased expression to attempt a file lock
in an unselected work area:
USE Sales NEW
USE Customer NEW
//
IF !Sales->(FLock())
? "Sales is in use by another"
ENDIF
Determine if the previous search operation succeeded
Syntax
Found() → lSuccess
Returns
Found() returns true (.T.) if the last search command was successful; otherwise, it returns false (.F.).
Description
Found() is a database function that determines whether a search operation (i.e., FIND, LOCATE, CONTINUE, SEEK, or SET RELATION) succeeded. When any of these commands are executed, Found() is set to true (.T.) if there is a match; otherwise, it is set to false (.F.).
If the search command is LOCATE or CONTINUE, a match is the next record meeting the scope and condition. If the search command is FIND, SEEK or SET RELATION, a match is the first key in the controlling index that equals the search argument. If the key value equals the search argument, Found() is true (.T.); otherwise, it is false (.F.).
The value of Found() is retained until another record movement command is executed. Unless the command is another search command, Found() is automatically set to false (.F.).
Each work area has a Found() value. This means that if one work area has a RELATION set to a child work area, querying Found() in the child returns true (.T.) if there is a match.
By default, Found() operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression (see example below).
Found() will return false (.F.) if there is no database open in the current work area.
Examples
■ This example illustrates the behavior of Found() after a
record movement command:
USE Sales INDEX Sales
? IndexKey(0) // Result: SALESMAN
SEEK "1000"
? Found() // Result: .F.
SEEK "100"
? Found() // Result: .T.
SKIP
? Found() // Result: .F.
■ This example tests a Found() value in an unselected work area
using an aliased expression:
USE Sales INDEX Sales NEW
USE Customer INDEX Customer NEW
SET RELATION TO CustNum INTO Sales
//
SEEK "Smith"
? Found(), Sales->(Found())
■ This code fragment processes all Customer records with the key
value "Smith" using Found() to determine when the key value changes:
USE Customer INDEX Customer NEW
SEEK "Smith"
DO WHILE Found()
.
. <statements>
.
SKIP
LOCATE REST WHILE Name == "Smith"
ENDDO
cFile is the name of the file to open, including the path if there is one.
nMode is the requested DOS open mode indicating how the opened file is to be accessed. The open mode is composed of elements from the two types of modes described in the tables below. If just the Access Mode is used, the file is opened non-sharable. The default open mode is zero, which indicates non-sharable and read-only.
FOpen() Access Modes
Mode Fileio.ch Operation
0 FO_READ Open for reading (default)
1 FO_WRITE Open for writing
2 FO_READWRITE Open for reading or writing
The Sharing Modes determine how other processes may access the file.
FOpen() Sharing Modes
Mode Fileio.ch Operation
0 FO_COMPAT Compatibility mode (default)
16 FO_EXCLUSIVE Exclusive use
32 FO_DENYWRITE Prevent others from writing
48 FO_DENYREAD Prevent others from reading
64 FO_DENYNONE Allow others to read or write
64 FO_SHARED Same as FO_DENYNONE
The Access Modes in combination (+) with the Sharing modes determine the accessibility of the file in a network environment.
Returns
FOpen() returns the file handle of the opened file in the range of zero to 65,535. If an error occurs, FOpen() returns -1.
Description
FOpen() is a low-level file function that opens an existing binary file for reading and writing, depending on the nMode argument. Whenever there is an open error, use FError() to return the DOS error number. For example, if the file does not exist, FOpen() returns -1 and FError() returns 2 to indicate that the file was not found. See FError() for a complete list of error numbers.
If the specified file is opened successfully, the value returned is the DOS handle for the file. This value is similar to an alias in the database system and is required to identify the open file to other file functions. It is, therefore, important to assign the return value to a variable for later use as in the example below.
Warning! This function allows low-level access to DOS files and devices. It should be used with extreme care and requires a thorough knowledge of the operating system.
Notes
■ Accessing files in other directories: FOpen() does not obey
either SET DEFAULT or SET PATH. Instead, it searches the current DOS directory and path setting unless a path is explicitly stated as part of the cFile argument.
Examples
■ This example uses FOpen() to open a file with sharable
read/write status and displays an error message if the open fails:
#include "Fileio.ch"
//
nHandle := FOpen("Temp.txt", FO_READWRITE + FO_SHARED)
IF FError() != 0
? "Cannot open file, DOS error ", FError()
BREAK
ENDIF
Execute a block of statements a specified number of times
Syntax
FOR <idCounter> := <nStart> TO <nEnd>
[STEP <nIncrement>]
<statements>...
[EXIT]
<statements>...
[LOOP]
NEXT
Arguments
idCounter is the name of the loop control or counter variable. If the specified idCounter is not visible or does not exist, a private variable is created.
nStart is the initial value assigned to idCounter. If nIncrement is negative, nStart must be less than nEnd.
TOnEnd defines the final value of idCounter. If nIncrement is negative, nStart must be greater than nEnd; otherwise, nStart must be less than nEnd.
STEPnIncrement defines the amount idCounter is changed for each iteration of the loop. nIncrement can be either positive or negative. If the STEP clause is not specified, idCounter is incremented by one for each iteration of the loop.
EXIT unconditionally branches control from within a FOR...NEXT construct to the statement immediately following the nearest NEXT statement.
LOOP branches control to the most recently executed FOR or DO WHILE statement.
Description
FOR...NEXT is a control structure that executes a block of statements a specified number of times. The control structure loops from the initial value of idCounter to the boundary specified by nEnd, moving through the range of values of the control variable for an increment specified by nIncrement. All expressions in the FOR statement are reevaluated for each iteration of the loop. The nStart and nEnd expressions, therefore, can be changed as the control structure operates.
A FOR loop operates until idCounter is greater than nEnd or an EXIT statement is encountered. Control then branches to the statement following the corresponding NEXT statement. If a LOOP statement is encountered, control branches back to the current FOR statement.
If nIncrement is a negative value, idCounter is decremented rather than incremented. The FOR loop, however, continues until idCounter is less than nEnd. This means that nEnd must be less than nStart when the FOR loop begins.
FOR loops are useful for traversing arrays where idCounter is used as the array subscript. See the example below.
FOR...NEXT constructs may be nested within any other control structures to any depth. The only requirement is that each control structure is properly nested.
Examples
■ This example traverses an array in ascending order:
nLenArray := Len(aArray)
FOR i := 1 TO nLenArray
<statements>...
NEXT
■ To traverse an array in descending order:
nLenArray := Len(aArray)
FOR i := nLenArray TO 1 STEP -1
<statements>...
NEXT
nHandle is the file handle obtained from FOpen(), FCreate(), or predefined by DOS.
cBufferVar is the name of an existing and initialized character variable used to store data read from the specified file. The length of this variable must be greater than or equal to nBytes. cBufferVar must be passed by reference and, therefore, must be prefaced by the pass- by-reference operator (@).
nBytes is the number of bytes to read into the buffer.
Returns
FRead() returns the number of bytes successfully read as an integer numeric value. A return value less than nBytes or zero indicates end of file or some other read error.
Description
FRead() is a low-level file function that reads characters from a binary file into an existing character variable. It reads from the file starting at the current DOS file pointer position, advancing the file pointer by the number of bytes read. All characters are read including control, null, and high-order (above Chr(127)) characters.
FRead() is similar in some respects to both FReadStr() and FSeek(). FReadStr() reads a specified number of bytes from a file up to the next null (Chr(0)) character. FSeek() moves the file pointer without reading.
If there is an error during the file read, FError() returns the DOS error number. See FError() for the list of error numbers.
Warning! This function allows low-level access to DOS files and devices. It should be used with extreme care and requires a thorough knowledge of the operating system.
Examples
■ This example uses FRead() after successfully opening a file to
read 128 bytes into a buffer area:
#define F_BLOCK 128
//
cBuffer := Space(F_BLOCK)
nHandle := FOpen("Temp.txt")
//
IF FError() != 0
? "File open error:", FError()
ELSE
IF FRead(nHandle, @cBuffer, F_BLOCK) <> F_BLOCK
? "Error reading Temp.txt"
ENDIF
FClose(nHandle)
ENDIF
nHandle is the file handle obtained from FOpen(), FCreate(), or predefined by DOS.
nBytes is the number of bytes to read, beginning at the current DOS file pointer position.
Returns
FReadStr() returns a character string up to 65,535 (64K) bytes. A null return value ("") indicates an error or end of file.
Description
FReadStr() is a low-level file function that reads characters from an open binary file beginning with the current DOS file pointer position. Characters are read up to nBytes or until a null character (Chr(0)) is encountered. All characters are read including control characters except for Chr(0). The file pointer is then moved forward nBytes. If nBytes is greater than the number of bytes from the pointer position to the end of the file, the file pointer is positioned to the last byte in the file.
Warning! This function allows low-level access to DOS files and devices. It should be used with extreme care and requires a thorough knowledge of the operating system.
Examples
■ This example displays the ASCII values of the first 16 bytes
of a text file:
#include "Fileio.ch"
//
nHandle := FOpen("New.txt", FC_NORMAL)
IF FError() != 0
? "File open error:", FError()
ELSE
cString := FReadStr(nHandle, 16)
? cString
FClose(nHandle)
ENDIF
cOldFile is the name of the file to be renamed, including the file extension. A drive letter and/or path name may also be included as part of the file name.
cNewFile is the new name of the file, including the file extension. A drive letter and/or path name may also be included as part of the name.
Returns
FRename() returns -1 if the operation fails and zero if it succeeds. In the case of a failure, FError() can be used to determine the nature of the error.
Description
FRename() is a file function that changes the name of a specified file to a new name and is identical to the RENAME command.
When FRename() is called, cOldFile is renamed only if it is located in the current DOS directory or in the specified path. FRename() does not use SET DEFAULT or SET PATH to locate cOldFile.
If the source directory is different from the target directory, the file moves to the target directory. In the instance that either cNewFile exists or is currently open, FRename() fails and returns -1, indicating that it did not perform its designated action. The nature of the error can be determined with FError().
Warning! Files must be CLOSEd before renaming. Attempting to rename an open file will produce unpredictable results. When a database file is renamed, the associated memo (.dbt) file must also be renamed. Failure to do so may compromise the integrity of your databases.
Examples
■ This example demonstrates a file rename:
IF FRename("OldFile.txt", "NewFile.txt") == -1
? "File error:", FError()
ENDIF
nHandle is the file handle obtained from FOpen(), FCreate(), or predefined by DOS.
nOffset is the number of bytes to move the file pointer from the position defined by nOrigin. It can be a positive or negative number. A positive number moves the pointer forward, and a negative number moves the pointer backward in the file.
nOrigin defines the starting location of the file pointer before FSeek() is executed. The default value is zero, representing the beginning of file. If nOrigin is the end of file, nOffset must be zero or negative.
Methods of Moving the File Pointer
Origin Fileio.ch Description
0 FS_SET Seek from beginning of file
1 FS_RELATIVE Seek from the current pointer position
2 FS_END Seek from end of file
Returns
FSeek() returns the new position of the file pointer relative to the beginning of file (position 0) as an integer numeric value. This value is without regard to the original position of the file pointer.
Description
FSeek() is a low-level file function that moves the file pointer forward or backward in an open binary file without actually reading the contents of the specified file. The beginning position and offset are specified as function arguments, and the new file position is returned. Regardless of the function arguments specified, the file pointer cannot be moved beyond the beginning or end of file boundaries.
Warning! This function allows low-level access to DOS files and devices. It should be used with extreme care and requires a thorough knowledge of the operating system.
Examples
■ This example uses FSeek() to determine the length of a file by
seeking from the end of file. Then, the file pointer is reset to the
beginning of file:
#include "Fileio.ch"
//
// Open the file read-only
IF (nHandle := FOpen("Temp.txt")) >= 0
//
// Get length of the file
nLength := FSeek(nHandle, 0, FS_END)
//
// Reset file position to beginning of file
FSeek(nHandle, 0)
FClose(nHandle)
ELSE
? "File open error:", FError()
ENDIF
■ This pseudofunction positions the file pointer at the last
byte in a binary file:
#define FileBottom(nHandle);
(FSeek(nHandle, 0, FS_END))
■ This pseudofunction positions the file pointer at the first
byte in a binary file:
#define FileTop(nHandle);
(FSeek(nHandle, 0))
■ This pseudofunction reports the current position of the file
pointer in a specified binary file:
#define FilePos(nHandle);
(FSeek(nHandle, 0, FS_RELATIVE))
idFunction is the name of the user-defined function to be declared. User-defined function names can be any length, but only the first 10 characters are significant. Names can contain any combination of characters, numbers, or underscores, but must begin with a character or an underscore. Leading underscores are not recommended since they are reserved for internal functions.
idParam list is the declaration of one or more parameter variables. Variables specified in this list are declared local.
STATIC FUNCTION declares a user-defined function that can be invoked only by procedures and user-defined functions declared in the same program (.prg) file.
LOCAL declares and optionally initializes a list of variables or arrays whose visibility and lifetime is the current function.
STATIC declares and optionally initializes a list of variables or arrays whose visibility is the current user-defined function and lifetime is the duration of the program.
FIELD declares a list of identifiers to use as field names whenever encountered. If the IN clause is specified, referring to the declared name includes an implicit reference to the specified alias.
MEMVAR declares a list of identifiers to use as private or public memory variables or arrays whenever encountered.
identifier and identifier list are labels to be used as variable or array names.
initializer is a value to which an array or variable is originally set in an inline expression.
RETURNexp passes control back to the calling procedure or user-defined function, returning the result of exp as the value of the function. Each function must have at least one RETURN statement that returns a value. RETURN statements can occur anywhere in the body of a function.
Description
The FUNCTION statement declares a user-defined function and an optional list of local variables to receive parameters often referred to as formal parameters. A user-defined function is a subprogram comprised of a set of declarations and statements executed whenever you refer to idFunction followed by an open and closed parentheses pair. A function definition begins with a FUNCTION statement which is the FUNCTION declaration and ends with the next FUNCTION statement, PROCEDURE statement, or end of file.
Functions encapsulate a computational block of code and then later create expressions using the value returned. Functions and procedures increase both readability and modularity, isolate change, and help manage complexity.
A function in CA-Clipper is the same as a procedure, except that it must return a value. The returned value can be any data type including an array, a code block, or NIL. Each function must begin with a FUNCTION statement and contain at least one RETURN statement with an argument. Function declarations cannot be nested within other function definitions. A user-defined function can be used wherever standard functions are supported, including expressions.
The visibility of function names falls into two classes. Functions that are visible anywhere in a program are referred to as public functions and declared with a FUNCTION statement. Functions that are visible only within the current program (.prg) file are referred to as static functions and declared with a STATIC FUNCTION statement. Static functions have filewide scope.
Static functions limit visibility of a function name, thereby restricting access to the function. Because of this, subsystems defined within a single program (.prg) file can provide an access protocol with a series of public functions and conceal the implementation details of the subsystem within static functions and procedures. Since the static function references are resolved at compile time, they preempt references to public functions which are resolved at link time. This ensures that within a program file, a reference to a static function executes that function if there is a name conflict with a public function.
For more information on user-defined functions, variable declarations, and parameter passing, refer to the "Basic Concepts" chapter in the Programming and Utilities Guide.
Notes
■ Calling a user-defined function: Use the same notation to call
a user-defined function as when calling a standard CA-Clipper function:
idFunction([argument list])
You can call a user-defined function within an expression or on a line by itself. If called on a line by itself, the return value is ignored.
You can also call a user-defined function as an aliased expression by prefacing it with an alias and enclosing it in parentheses:
idAlias->(idFunction(argument list))
When you call a user-defined function as an aliased expression, the work area associated with idAlias is selected, the expression is executed, and the original work area is then reselected. You can specify an aliased expression on a line by itself, as you would any other expression.
A user-defined function in CA-Clipper may call itself recursively. This means you can make a reference to a user-defined function in statements or expressions of the same user-defined function definition.
■ Parameters: User-defined functions, like procedures, can
receive parameters passed from a calling procedure, user-defined function, or DOS command line. A parameter is a place holder for a value or reference. In CA-Clipper, there are two ways to express parameters: you can declare a list of local variable names as a part of the FUNCTION declaration (referred to as formal parameters), or you can specify a list of private variables in a separate PARAMETERS statement. Note that you cannot mix a declaration of formal parameters with a PARAMETERS statement. Attempting this will result in a fatal compiler error.
Functions receive parameters in the order passed. In CA-Clipper, the number of parameters does not have to match the number of arguments passed. You can skip arguments or omit them from the end of the argument list. A parameter not receiving a value or reference is initialized to NIL. You can skip a parameter by passing NIL. If arguments are specified, PCount() returns the position of the last argument passed. (If more arguments are passed than are parameters, they are ignored.)
Parameters specified in a user-defined function can receive arguments passed by value or reference. The default method for expressions and variables is by value. This includes variables that contain references to arrays and objects. All variables except field variables, when prefaced with the pass-by-reference operator (@), are passed by reference. Field variables cannot be passed by reference and are always passed by value.
Examples
■ This example demonstrates a user-defined function that formats
numeric values as currency:
? Currency( 1000 ) // Result: $1,000.00
FUNCTION Currency( nNumber )
LOCAL cNumber
IF nNumber < 0
cNumber := Transform(-1 * nNumber, ;
"999,999,999,999.99")
cNumber := PadL("($" + LTrim(cNumber) + ")", ;
Len(cNumber))
ELSE
cNumber := Transform(nNumber, ;
"999,999,999,999.99")
cNumber := PadL("$" + LTrim(cNumber), ;
Len(cNumber))
ENDIF
RETURN cNumber
■ This example demonstrates a user-defined function that takes a
character string formatted as a comma-separated list and returns an
array with one element per item:
aList := ListAsArray("One, Two")
// Result: {"One", "Two"}
FUNCTION ListAsArray( cList )
LOCAL nPos
// Define an empty array
LOCAL aList := {}
//
DO WHILE (nPos := At(",", cList)) != 0
// Add a new element
AAdd(aList, SubStr(cList, 1, nPos - 1))
cList := SubStr(cList, nPos + 1)
ENDDO
AAdd(aList, cList)
//
// Return the array
RETURN aList
■ This example checks for a skipped argument by comparing the
parameter to NIL:
FUNCTION MyFunc( param1, param2, param3 )
IF param2 == NIL
param2 := "default value"
ENDIF
.
. <statements>
.
RETURN NIL
■ This example uses the user-defined function, Currency()
(defined above), as an aliased expression:
USE Invoices NEW
USE Customer NEW
? Invoices->(Currency(Amount))
nHandle is the file handle obtained from FOpen(), FCreate(), or predefined by DOS.
cBuffer is the character string to write to the specified file.
nBytes indicates the number of bytes to write beginning at the current file pointer position. If omitted, the entire content of cBuffer is written.
Returns
FWrite() returns the number of bytes written as an integer numeric value. If the value returned is equal to nBytes, the operation was successful. If the return value is less than nBytes or zero, either the disk is full or another error has occurred.
Description
FWrite() is a low-level file function that writes data to an open binary file from a character string buffer. You can either write all or a portion of the buffer contents. Writing begins at the current file position, and the function returns the actual number of bytes written.
If FWrite() results in an error condition, FError() can be used to determine the specific error.
Warning! This function allows low-level access to DOS files and devices. It should be used with extreme care and requires a thorough knowledge of the operating system
Examples
■ This example copies the contents of one file to another:
#include "Fileio.ch"
#define F_BLOCK 512
//
cBuffer := Space(F_BLOCK)
nInfile := FOpen("Temp.txt", FO_READ)
nOutfile := FCreate("Newfile.txt", FC_NORMAL)
lDone := .F.
//
DO WHILE !lDone
nBytesRead := FRead(nInfile, @cBuffer, F_BLOCK)
IF FWrite(nOutfile, cBuffer, nBytesRead) < ;
nBytesRead
? "Write fault: ", FError()
lDone := .T.
ELSE
lDone := (nBytesRead == 0)
ENDIF
ENDDO
//
FClose(nInfile)
FClose(nOutfile)
aBmpArray defines the pointer created with GBMPLOAD().
-OR-
cFile defines the .BMP file to be displayed.
nX is the position of the starting point on the X-axis (column).
nY is the position of the starting point on the Y-axis (line).
nTransColor is the color to be excluded.
If nColor is set, all colors in the image are displayed except nColor.
Returns
GBMPDISP() always returns NIL.
Description
GBMPDISP() displays a bitmap (.BMP) or icon (.ICO) file previously loaded into memory or display a BMP directly from disk. This function can be used only if you have set the screen to a graphic mode using SET VIDEOMODE. GBMPDISP() respects the constraints defined by GSETCLIP().
Warning! The current color palette is used when you display a .BMP. Be aware that if you allow users to modify the color palette, the colors used in creating your .BMP may be changed because of the current palette components.
Notes
It is possible to create visual effects on top of a .BMP, such as a button that appears to be depressed when the user clicks on it. This can be done by superimposing a rectangle in XOR mode:
#include "Llibg.ch" LOCAL aMyButton SET VIDEOMODE TO LLG_VIDEO_VGA_640_480_16 // Load the BMP aMyButton := gBmpload ("MyButton.BMP")
DO WHILEmState()[LLM_STATE_LEFT] == LLM_BUTTON_DOWN . . // Your code . ENDDO
// When the mouse button is released we reload // the BMP to restore the original look
gRect(100,;
200,; 100 + aMyButton[LLG_BMP_X],;
200 + aMyButton[LLG_BMP_Y],;
LLG_FILL,;
8,;
LLG_MODE_XOR)
Examples
■ This example displays buttons previously stored in aIcons
using gBmpLoad():
gBmpDisp(aIcons,100,200)
■ This example loads and displays a background without using a
variable. In this case, the area occupied in VMM when the array is
loaded, is freed by CA-Clipper once the display ends.
gBmpDisp(gBmpLoad("MyDesk.BMP") , 0 , 0 )
Load a bitmap (.bmp) or icon (.ico) file into memory
Syntax
GBMPLOAD(<cFileName>) → aBmpArray
Arguments
cFileName is a character value that specifies the name of .bmp or .ico file to load into VMM memory.
Returns
GBMPLOAD() returns a reference to aBmpArray which is the pointer to the VMM region containing the .BMP or .ICO (not a black and white icon). The first two elements of aBmpArray contain the height and width of the .BMP or .ICO in pixels. Do not modify this array before passing it to GBMPDISP(). The following table shows the array structure:
aBmpArray Structure
Array Position Return Value
LLG_BMP_X Returns size on the X axis
LLG_BMP_Y Returns size on the Y axis
The size and elements of this array should never be changed.
Description
GBMPLOAD() allows you to load one or more .BMP or .ICO files into memory without having to display them. This function is useful when you want to load a group of small .BMP files which are used often in an application (e.g., buttons). It avoids having to load the .BMP file each time you display it.
Warning! It is not a good idea to keep backgrounds or images in memory unless you have a great deal of memory. This also includes any variable pointing to the variables which contain the .BMP.
Notes
When a .BMP or .ICO is stored in a LOCAL variable, the memory occupied in the VMM is automatically freed when the function returns. You can free the memory at any time by assigning NIL to the variable. It is not necessary to be in graphic mode to use GBMPLOAD(), but it is necessary to be in graphic mode before calling GBMPDISP().
Examples
■ This example stores all the buttons used by an application in
an array:
STATIC aIcons:= {}
AAdd(aIcons, GBMPLOAD('ARROW_U.BMP'))
AAdd(aIcons, GBMPLOAD('ARROW_D.BMP'))
AAdd(aIcons, GBMPLOAD('ARROW_L.BMP'))
AAdd(aIcons, GBMPLOAD('ARROW_R.BMP'))
// Set video to graphic mode
SET VIDEOMODE TO LLG_VIDEO_VGA_640_480_16
// Display the ARROW_U.BMP
GBMPDISP(aIcons[1], 100, 200)
Provides objects for interactive editing of database fields and variables
Description
A Get object is a general purpose mechanism for editing data. It is used in CA-Clipper to implement the @...GET and READ commands. Get objects provide a sophisticated architecture for formatting and editing data, including cursor navigation and data validation. Data validation is performed via user-supplied code blocks, and display formatting can be controlled using standard picture strings.
Normally, a Get object is associated with a particular variable (referred to as the GET variable). The Get object does not directly access this variable; instead, the variable is manipulated by evaluating a supplied code block. When a Get object is created using the standard @...GET command, a code block is automatically created which provides access to the variable named in the command. For a Get object created with the GetNew() function, you must specify an appropriate code block.
A Get object evaluates the supplied code block to retrieve the value of the GET variable. The value is converted to a displayable form and copied into a buffer referred to as the editing buffer. You can display the editing buffer on the screen for editing. Programmable behaviors allow the navigation of the editing buffer and subsequent copying of its contents back to the GET variable.
Methods link
Class Function
GetNew() Create a new Get object
GetNew([nRow], [nCol], [bBlock], [cVarName],
[cPicture], [cColorSpec]) → oGet
Returns
GetNew() returns a new Get object with the row, col, block, picture, and colorSpec instance variables set from the supplied arguments.
Exported Instance Variables
badDate Indicates if the editing buffer contains an invalid date
badDate
Contains a logical value indicating that the editing buffer does not represent a valid date. Get:badDate contains true (.T.) when the Get object is a date type and the date represented by the contents of the editing buffer is invalid. Get:badDate contains false (.F.) when the date is valid or the GET is not editing a date value.
block Code block to associate Get with a variable
block (Assignable)
Contains a code block that associates the Get object with a variable. The code block takes an optional argument that should assign the value of the argument to the variable. If the argument is omitted, the code block should return the current value of the variable.
If the GET variable is an array element, Get:block always returns the base of the array. The subscript(s) in the expression are stored internally. Thus, in the case of GETs on array elements, you cannot assign or retrieve the value of the array element by executing Get:block. Setting and getting may be done on array element GET variables (and simple variables as well) by use of the varGet() and varPut() methods, defined below.
Note: Use of the varGet and varPut messages—instead of directly evaluating the variable block in the GET—is the preferred method of accessing the GET variable.
buffer Character value that defines the editing buffer
buffer (Assignable)
Contains a character value which is the editing buffer used by the Get object. Get:buffer is meaningful only when the Get object has input focus. At other times, it contains NIL and any attempts to assign a new value are ignored.
cargo User-definable variable
cargo (Assignable)
Contains a value of any data type unused by the Get system. Get:cargo is provided as a user-definable slot, allowing arbitrary information to be attached to a Get object and retrieved later.
changed Indicates whether the Get:buffer has changed
changed
Contains a logical value indicating whether the Get:buffer has changed since the GET received input focus. Get:changed contains true (.T.) if the buffer has changed; otherwise, it contains false (.F.).
clear Indicates whether the editing buffer should be cleared
clear (Assignable)
Contains a logical value indicating whether the editing buffer should be cleared before any more values are entered. Get:clear is set true (.T.) by Get:setFocus() and Get:undo() when the G variable is a numeric type or when Get:picture contains the "@K" picture function. At all other times, it contains false (.F.).
col Get column number
col (Assignable)
Contains a numeric value defining the screen column where the Get is displayed.
colorSpec Display attributes string
colorSpec (Assignable)
Contains a character string defining the display attributes for the Get object. The string must contain two color specifiers. The first, called the unselected color, determines the color of the Get object when it does not have input focus. The second, called the selected color, determines the color of the GET when it has input focus.
If no colors are specified, Get:colorSpec is initialized using the current SetColor() colors. The SetColor() unselected and enhanced colors are used as the Get object's unselected and selected colors, respectively. See the SetColor() entry in this chapter for more information on color specifiers.
decPos Decimal point position within the editing buffer
decPos
Contains a numeric value indicating the decimal point position within the editing buffer. Get:decPos is meaningful only when the value being edited is numeric and the Get object has input focus. Otherwise, it contains NIL.
exitState Means by which the user exited the Get
exitState (Assignable)
Contains a numeric value used in the CA-Clipper version of Getsys.prg to record the means by which a Get object was exited.
GET Exit States
Number Getexit.ch Meaning
0 GE_NOEXIT No exit attempted, prepare for editing
1 GE_UP Go to previous
2 GE_DOWN Go to next
3 GE_TOP Go to first
4 GE_BOTTOM Go to last
5 GE_ENTER edit normal end
6 GE_WRITE Terminate READ state with save
7 GE_ESCAPE Terminate READ state without save
8 GE_WHEN WHEN clause unsatisfied
Getexit.ch contains manifest constants for the Get:exitState values.
hasFocus Logical value indicating the input focus
hasFocus
Contains a logical value that indicates if the Get object has input focus. Get:hasFocus contains true (.T.) if the Get object has input focus; otherwise, it contains false (.F.).
message Character string displayed on the Get system's status bar
message (Assignable)
Contains a character string that is displayed on the Get system's status bar line when the GET has input focus. Typically, it describes the anticipated contents of, or user response to the GET. Refer to the READ command for details pertaining to the Get system's status bar.
minus Indicates if a minus sign has been entered
minus (Assignable)
Contains a logical value indicating that a minus sign (-) has been added to the editing buffer. Get:minus is set to true (.T.) only when the Get object is a numeric type, the current value of the editing buffer is zero and the last change to the editing buffer was the addition of the minus sign. It is cleared when any change is made to the buffer.
name Get variable name
name (Assignable)
Contains a character string representing the name of the GET variable. This value is optional and can be assigned at your discretion. With Get objects created using the standard @...GET command, Get:name always contains the GET variable name.
The Get object itself ignores this variable. It is used by the standard READ command and ReadModal() function to implement the ReadVar() function (see the ReadVar() entry in this chapter).
original Character string containing the original value of the Get
original
Contains a value of any data type that is a copy of the value in the GET variable at the time the Get object acquired input focus. This value implements the Get:undo message. Get:original is meaningful only while the GET has input focus. At all other times, it contains NIL.
picture PICTURE string
picture (Assignable)
Contains a character value defining the PICTURE string that controls formatting and editing for the Get object. See the @...GET entry in this chapter for more information on PICTURE strings.
pos Current cursor position within the editing buffer
pos
Contains a numeric value indicating the position of the cursor within the editing buffer. Get:pos is meaningful only when the Get object has input focus. At all other times, it contains NIL.
postBlock Code block to validate a newly entered value
postBlock (Assignable)
Contains an optional code block that validates a newly entered value. If present, the Get:postBlock should contain an expression that evaluates to true (.T.) for a legal value and false (.F.) for an illegal value. For Get objects created with the standard @...GET...VALID command, Get:postBlock is assigned the expression specified in the VALID clause.
The Get object itself ignores this variable. It is used by the standard READ command to implement the VALID clause.
During postvalidation the Get:postBlock is passed a reference to the current Get object as an argument. Note that this differs from the CA-Clipper 5.0 behavior where the Get:postBlock was passed the updated value of the GET variable, and a logical value representing whether the Get object had been edited.
preBlock Code block to decide if editing is permitted
preBlock (Assignable)
Contains an optional code block that decides whether editing should be permitted. If present, the Get:preBlock should evaluate to true (.T.) if the cursor enters the editing buffer; otherwise, it should evaluate to false (.F.). For Get objects created with the standard @...GET...WHEN command, Get:preBlock is initialized with the expression specified in the WHEN clause.
The Get object itself ignores this variable. It is used by the standard READ command to implement the WHEN clause.
During prevalidation, the Get:preBlock is passed a reference to the current Get object as an argument. Note that this behavior differs from CA-Clipper 5.0 where no arguments were passed to Get:preBlock when it was run during prevalidation.
reader Contains a block to affect READ behavior on a Get object
reader
Contains a code block to implement special READ behaviors for any GET. If Get:reader contains a code block, ReadModal() evaluates that block to READ the GET (the Get object is passed as an argument to the block). The block may in turn call any desired function to provide custom editing of the Get object. If Get:reader does not contain a code block, ReadModal() uses a default read procedure (GetReader()) for the Get object.
Note that Get:reader allows particular Get objects to have specialized READ behaviors without changing the standard ReadModal() function. This preserves compatibility for GETs which are to be handled in the customary way and also eliminates potential conflicts between different extensions to the GET/READ system.
rejected Indicates if last insert/overStrike character was rejected
rejected
Contains a logical value indicating whether the last character specified by a Get:insert or Get:overStrike message was placed in the editing buffer. Get:rejected contains true (.T.) if the last character was rejected; otherwise, it contains false (.F.). Note that any subsequent text entry message resets this variable.
row Get row number
row (Assignable)
Contains a numeric value defining the screen row where the GET displays.
subscript Information about array Get objects
subscript (Assignable)
Contains an array of numeric values representing the subscripts of a GET array element. Each element of Get:subscript represents a dimension of the GET array. For example:
@ 1,1 GET aTestA[4] // Get:subscript contains {4} @ 1,1 GET aTestB[3,6] // Get:subscript contains {3,6}
If the GET does not involve an array, Get:subscript contains NIL.
type Get variable data type
type
Contains a single letter representing the data type of the GET variable. For more information on the values that represent data types, refer to the ValType() entry in this chapter.
typeOut Indicates attempt to move the cursor out of editing buffer
typeOut
Contains a logical value indicating whether the most recent message attempted to move the cursor out of the editing buffer, or if there are no editable positions in the buffer. Get:typeOut contains true (.T.) if the last message satisfied this condition. Note, Get:typeOut is reset by any message that moves the cursor.
Exported Methods
State Change Methods
assign() Assigns the editing buffer contents to the Get variable
assign() → self
Assigns the value in the editing buffer to the GET variable by evaluating Get:block with the buffer value supplied as its argument. This message is meaningful only when the Get object has input focus.
colorDisp() Changes a Get object's color then redisplays it
colorDisp([cColorString]) → self
Get:colorDisp() is a method that changes a Get object's colors and redisplays it. It is exactly equivalent to assigning Get:colorSpec and issuing Get:display().
display() Displays the Get on the screen
display() → self
Displays the GET on the screen. If the Get object has input focus, the Get:buffer displays in its selected color and the cursor is placed at the screen location corresponding to the current editing position within the buffer. If the GET does not have input focus, the Get:block is evaluated and the result displays in the GET's unselected color with no cursor.
HitTest() Indicates position of mouse cursor relative to Get object
HitTest(nRow, nColumn) → self
Determines the screen position specified by nRow and nColumn is on the Get object.
Applicable Hit Test Return Values
Value Constant Description
0 HTNOWHERE The mouse cursor is not within the region of the
screen that the GET occupies
-1025 HTCAPTION The mouse cursor is on the GET's caption
-2049 HTCLIENT The mouse cursor is on the GET
Button.ch contains manifest constants for the Get:hitTest() return values.
killFocus() Takes input focus away from the Get object
killFocus() → self
Takes input focus away from the Get object. Upon receiving this message, the Get object redisplays its editing buffer and discards its internal state information.
reset() Resets the internal state information of the Get
reset() → self
Resets the Get object's internal state information. This includes resetting the editing buffer to reflect the GET variable's current value and setting the cursor position to the first editable position within the buffer. This message has meaning only when the Get object has input focus.
setFocus() Gives input focus to the Get object
setFocus() → self
Gives input focus to the Get object. Upon receiving this message, the Get object creates and initializes its internal state information, including the exported instance variables: Get:buffer, Get:pos, Get:decPos, and Get:original. The contents of the editing buffer are then displayed in the GET's selected color.
undo() Sets the Get variable back to Get:original
undo() → self
Sets the GET variable back to the value it had when the GET acquired input focus. This message has meaning only while the GET has input focus.
The effect of the Get:undo() message is equivalent to assigning the GETvariable from the saved value in Get:original and then sending the Get:reset() message.
unTransform() Converts character value to its original data type
unTransform() → xValue
Converts the character value in the editing buffer back to the data type of the original variable. Get:assign() is equivalent to Get:varPut (Get:unTransform()).
updateBuffer() Updates the editing buffer and redisplays the Get
updateBuffer() → self
Sets the editing buffer to reflect the current value of the Get variable, and redisplays the GET. This message has meaning only while the GET has input focus.
varGet() Returns the current value of the Get variable
varGet() → GetVarValue
Returns the current value of the GET variable. For simple GET variables this is equivalent to executing Get:block:
aGet:varGet() == Eval(aGet:block)
However, if the GET variable is an array element, Eval(aGet:block) will not return the value of the GET variable; in this case, you must use varGet(). An example of varGet() may be found in the ReadModal() function, defined in Getsys.prg.
varPut() Sets the Get variable to the passed value
varPut() → Value
Sets the GET variable to the passed value. For simple GET variables this is equivalent to executing Get:block with an argument:
aGet:varPut(aValue) == Eval(aGet:block, aValue)
However, if the GET variable is an array element, Eval(aGet:block, aValue) will not set the value of the GET variable; in this case use of varPut() is required.
Cursor Movement Methods
end() Moves the cursor to the rightmost position
end() → self
Moves the cursor to the rightmost editable position within the editing buffer.
home() Moves the cursor to the leftmost position
home() → self
Moves the cursor to the leftmost editable position within the editing buffer.
Moves the cursor left to the nearest editable position within the editing buffer. If there is no editable position to the left, the cursor position is left unchanged.
Moves the cursor right to the nearest editable position within the editing buffer. If there is no editable position to the right, the cursor position is left unchanged.
toDecPos() Moves the cursor to the immediate right of Get:decPos
toDecPos() → self
Moves the cursor to the immediate right of the decimal point position in the editing buffer. This message is only meaningful when editing numeric values.
wordLeft() Moves the cursor left one word
wordLeft() → self
Moves the cursor one word to the left within the editing buffer. If the cursor is already at the leftmost editable position, it is left unchanged.
wordRight() Moves the cursor right one word
wordRight() → self
Moves the cursor one word to the right within the editing buffer. If the cursor is already at the rightmost editable position, it is left unchanged.
Editing Methods
backspace() Moves the cursor to the left and deletes one character
backspace() → self
Deletes the character to the left of the cursor moving the cursor one position to the left. If the cursor is already at the leftmost editable position in the editing buffer, this message has no effect.
delete() Deletes the character under the cursor
delete() → self
Deletes the character under the cursor.
delEnd() Deletes from current cursor position to the end of the Get
delEnd() → self
Deletes from the current character position to the end of the GET, inclusive.
delLeft() Deletes the character to the left of the cursor
delLeft() → self
Deletes the character to the left of the cursor.
delRight() Deletes the character to the right of the cursor
delRight() → self
Deletes the character to the right of the cursor.
delWordLeft() Deletes the word to the left of the cursor
delWordLeft() → self
Deletes the word to the left of the cursor.
delWordRight() Deletes the word to the right of the cursor
delWordRight() → self
Deletes the word to the right of the cursor.
Text Entry Methods
insert() Inserts characters into the editing buffer
insert(cChar) → self
Inserts cChar into the editing buffer at the current cursor position, shifting the existing contents of the buffer to the right. The cursor is then placed one position to the right of the inserted string.
overStrike() Overwrites characters in the editing buffer
overStrike(cChar) → self
Puts cChar into the editing buffer at the current cursor position, overwriting the existing contents of the buffer. The cursor is placed one position to the right of the inserted string.
Examples
■ This example creates a new Get object, assigns some new
attributes to its instance variables, and then edits the GET with the
ReadModal() function:
LOCAL cVar := Space(10)
//
// Create a new Get object
objGet := GetNew()
//
// Assign some instance variables
objGet:row := 10
objGet:col := 10
//
// Assign the name of the associated
// variable and the block
objGet:name := "cVar"
objGet:block := { |cValue| IF(PCount() > 0,;
cVar := cValue, cVar) }
//
objGet:picture := "@!"
objGet:colorSpec := "BG+/B, W+/BG"
objGet:postBlock := { |oGet| !Empty(oGet:varGet()) }
//
// Edit the single Get object
ReadModal({objGet})
GetActive() returns the Get object referenced by oGet. If oGet is not specified, then the current active Get object within the current READ is used. If there is no READ active when GetActive() is called, it returns NIL.
Description
GetActive() is an environment function that provides access to the active Get object during a READ. The current active Get object is the one with input focus at the time GetActive() is called.
Examples
■ This code uses a WHEN clause to force control to branch to a
special reader function. Within this function, GetActive() retrieves
the active Get object:
@ 10, 10 GET x
@ 11, 10 GET y WHEN MyReader()
@ 12, 10 GET z
READ
// Called just before second get (above)
// becomes current
FUNCTION MyReader
LOCAL objGet // Active Get holder
objGet := GetActive() // Retrieve current
// active Get
BarCodeRead( objGet )
RETURN (.F.) // Causes Get to be
// skipped in READ
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, source file is Getsys.prg.
GetList is a reference to the current list of Get objects.
oMenu is a reference to any top bar menu.
nMsgRow is a numeric value representing the row of the message bar.
nMsgLeft is a numeric value representing the left column of the message bar.
nMsgRight is a numeric value representing the right column of the message bar.
cMsgColor is a character string representing the colors to be used for the message bar text.
Returns
GetApplyKey() always returns NIL.
Description
GetApplyKey() is a Get system function that applies an Inkey() value to a Get object. Keys are applied in the default way. That is, cursor movement keys change the cursor position within the GET, data keys are entered into the GET, etc.
If the key supplied to GetApplyKey() is a SET KEY, GetApplyKey() will execute the set key and return; the key is not applied to the Get object.
Notes
■ Focus: The Get object must be in focus before keys are
applied. Refer to Get:setFocus and Get:killFocus for more information.
■ CLEAR GETS: The Get object must be in focus before keys are
applied. Refer to Get:setFocus and Get:killFocus for more information.
Examples
This example will apply keystrokes until Exit:
WHILE (oGet:exitState == GE_NOEXIT)
GETAPPLYKEY (oGet, Inkey(0), GetList, oMenu, nMsgRow,;
nMsgLeft, nMsgRight, nMsgColor)
ENDDO
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, source file is Getsys.prg.
GetDoSetKey() is a function that executes a SET KEY code block, preserving the context of the passed Get object.
Note that the procedure name and line number passed to the SET KEY block are based on the most recent call to ReadModal().
Notes
■ If a CLEAR GETS occurs in the SET KEY code, Get:exitState is
set to GE_ESCAPE. In the standard system this cancels the current Get object processing and terminates ReadModal().
Examples
■ The following example determines if the last key pressed,
nKey, has a SET KEY associated with it. If it does, then GETDOSETKEY
is called to execute that block on the current GET.
IF ((bKeyBlock := SETKEY (nKey)) == NIL)
GETDOSETKEY (bKeyBlock, oGet)
ENDIF
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, source file is Getsys.prg.
Retrieve the contents of a DOS environment variable
Syntax
GetEnv(<cEnvironmentVariable>) → cString
Arguments
cEnvironmentVariable is the name of the DOS environment variable. When specifying this argument, you can use any combination of uppercase and lowercase letters; GetEnv() is not case-sensitive.
Returns
GetEnv() returns the contents of the specified DOS environment variable as a character string. If the variable cannot be found, GetEnv() returns a null string ("").
Description
GetEnv() is an environment function that lets you retrieve information from the DOS environment into an application program. Typically, this is configuration information, including path names, that gives the location of files (database, index, label, or reports). This function is particularly useful for network environments.
Notes
■ Empty return value: If you are certain that an environment
variable exists and yet GetEnv() always returns a null string (""), be sure there are no spaces between the environment variable name and the first character of the string assigned to it in the DOS SET command.
■ Compatibility: In previous releases of CA-Clipper, the
function was called GetE(). This abbreviated form of GetEnv() is still operational.
Examples
■ This example retrieves the current DOS PATH setting, making it
the current CA-Clipper PATH:
cPath := GetEnv("PATH")
SET PATH TO (cPath)
■ This example uses environment variables to configure the
specific locations of files. When you set up a system, define
environment variables that contain the location of various file types
as well as the CLIPPER environment variable (see "The Runtime
Environment" chapter in the Programming and Utilities Guide), like
this:
C>SET LOC_DBF=<database file path>
C>SET LOC_NTX=<index file path>
C>SET LOC_RPT=<report file path>
In the configuration section of your application program, assign the
contents of the environment variables to variables. Then when you
access a file, preface the reference with the path variable as
follows:
cDdfDirectory := GetEnv("LOC_DBF")
USE (cDdfDirectory + "Invoices")
GetPostValidate() returns a logical value indicating whether the Get object has been postvalidated successfully.
Description
GetPostValidate() is a Get system function that validates a Get object after editing, including evaluating Get:postBlock (the VALID clause) if present.
The return value indicates whether the GET has been postvalidated successfully. If a CLEAR GETS is issued during postvalidation, Get:exitState is set to GE_ESCAPE and GetPostValidate() returns true (.T.).
Notes
■ In the default system, a Get:exitState of GE_ESCAPE cancels
■ This example calls GETPOSTVALIDATE to determine whether or not
the VALID clause of oGet is satisfied. If not, then the user is not
allowed to exit from the Get object.
IF (! GETPOSVALIDATE (oGet))
oGet : exitState := GE_NOEXIT
ENDIF
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, source file is Getsys.prg.
GetPreValidate() returns a logical value indicating whether the Get object has been prevalidated successfully.
Description
GetPreValidate() is a function that validates the Get object for editing, including evaluating Get:preBlock (the WHEN clause) if it is present. The logical return value indicates whether the GET has been prevalidated successfully.
Get:exitState is also set to reflect the outcome of the prevalidation:
Get:exitState Values
Getexit.ch Meaning
GE_NOEXIT Indicates prevalidation success, okay to edit
GE_WHEN Indicates prevalidation failure
GE_ESCAPE Indicates that a CLEAR GETS was issued
Note that in the default system, a Get:exitState of GE_ESCAPE cancels the current GET and terminates ReadModal().
Examples
■ This example demonstrates the GetPreValidate() function.
IF GETPREVALIDATE (oGet)
// process the get
ELSE
// WHEN clause not satisfied
// give a warning to the user
ENDIF
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, source file is Getsys.prg.
GetList is an array of all the Get objects in the current Get list.
oMenu is a reference to a TopBarMenu object.
nMsgRow is a numeric value representing the row number on the screen where the message bar is located.
nMsgLeft is a numeric value representing the left border of the row bar.
nMsgRight is a numeric value representing the right border of the row bar.
cMsgColor is a character string representing the color string to be used for the message bar.
Returns
GetReader() always returns NIL.
Description
GetReader() is a GET function that implements the standard READ behavior for GETs. By default, ReadModal() uses the GetReader() function to read Get objects. GetReader() in turn uses other functions in Getsys.prg to do the work of reading the Get object.
Notes
■ If a Get object's Get:reader instance variable contains a code
block, ReadModal() will evaluate that block in lieu of the call to GetReader(). For more information refer to the Get:reader reference.
Examples
■ This example sets the current Get object to the first GET in
the Get list. Then, a READ is performed on this GET which has no
menu object, but includes a message bar at row 25 from column 0 to
column 80. The color of the text on the message bar is white with a
red background.
oGet := GetList [1]
GETREADER (oGet, Getlist, NIL,25,;
0,80,"W+/R")
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, source file is Getsys.prg.
nXc, nYc, nRadiusX, and nRadiusY define the ellipse center point coordinates in pixels.
Note: If nRadiusX and nRadiusY have the same value, the result will be a circle.
nDegStart is the value of the starting angle in degrees. The default value is 0.
nDegEnd is the value of the final angle in degrees. The default value is 360.
Note: Changing the values of nDegStart and nDegEnd allows you to draw arcs of a circle or ellipse and sections of a "pie chart."
nStyle defines the style of the ellipse using one of the constants listed in the table below:
Ellipse Style Constants
Constant Description
LLG_FILL The ellipse is displayed first and then filled with the
color and mode specified below
LLG_FRAME Display of the ellipse is restricted to its contour in the
color and mode specified below
nColor is a numeric value representing the display color. If this parameter is missing, the last color specified in a call to a CA-Clipper function is used. The value range is limited to the number of colors available in the selected video mode. In 16-color modes, valid values are between 0 and 15. In 256-color modes, valid values are between 0 and 255.
nMode is a numeric value that represents the display mode. The following are valid nMode values:
Display Mode Constants
Constant Description
LLG_MODE_SET Display in SET mode (ignores any pixels present under the
line displayed). This is the most common display mode.
LLG_MODE_AND Display in AND mode (executes an AND on pixels present
under the line at display time and on the display color).
LLG_MODE_OR Display in OR mode (executes an OR on pixels present
under the line at display time and on the display color).
LLG_MODE_XOR Display in XOR mode (executes an XOR on pixels present
under the line at display time and on the display color).
See note.
Note: This method allows you to move objects around on the screen without damaging the background. To retrieve the initial background, just repeat the call for display in XOR mode. If the display mode parameter is missing, the last mode specified in a call to a CA-Clipper function is used.
nOutLineColor is a numeric value representing the outline color. If this parameter is missing, the last color specified in a call to a CA-Clipper function is used. The value range is limited to the number of colors available in the selected video mode. In 16-color modes, valid values are between 0 and 15. In 256-color modes, valid values are between 0 and 255.
nHeight3D is a numeric value representing the height of the 3-D effect in pixels.
Returns
GELLIPSE() always returns NIL.
Description
GELLIPSE() draws an ellipse or circle. This function can be used only if you have set the screen to a graphic mode using SET VIDEOMODE. This function respects the constraints defined by GSETCLIP().
Examples
■ This example displays an ellipse in a region limited by
clipping:
// Switch to graphic mode
SET VIDEOMODE TO LLG_VIDEO_VGA_640_480_16
// Restrict the display region to one portion of the screen
GSETCLIP(100,100,300,300)
// Draw a quarter section of an ellipse
GELLIPSE(200, 200, 160, 230, 045,;
135, LLG_FILL, 12, LLG_MODE_SET)
QUIT // End of application
aFont is a pointer to the VMM region where the .FND font is loaded. aFont would have been created with an earlier call to GFNTLOAD().
Returns
GFNTERASE() always returns NIL.
Description
GFNTERASE() erases a specified font from memory. Since CA-Clipper is unable to reallocate the memory occupied by a loaded font (i.e., no automatic garbage collection), it is your responsibility to release this memory. This can be done with the following:
aFont2Erase := GFNTERASE(aFont2Erase)
Examples
■ This example loads a Font file called MyFont .FND:
FUNCTION ShowOneFont (cString)
LOCAL aFont
// Load a specific font file into memory
aFont := GFNTLOAD("MyFont.FND")
// Display cString using the loaded font
GWRITEAT(X , Y , cString, nColor, LLG_MODE_SET, aFont)
// *Important* You must erase the font from memory if it is
// no longer used. This is because CA-Clipper's VMM is
// unable to automatically free the memory occupied by aFont.
GFNTERASE(aFont)
RETURN NIL
cFontFile is a character value that represents the name of the font file to load.
Returns
GFNTLOAD() returns a pointer to the VMM region where the font is loaded. This value can later be used as input to GFNTERASE().
Description
CA-Clipper supports two types of fonts:
1. Video ROM fonts—.FND
Video ROM .FND fonts are used in all the standard CA-Clipper terminal calls such as DevOut(), TBrowse(), and GWRITEAT(). The size of .FND fonts is always 16x8. If you want to use a different size font, such as 8x8, you will need to supply the font file.
2. Windows Bitmap fonts—.FNT
The Windows Bitmap .FNT fonts can be used with the GWRITEAT() function.
Using .FND fonts: The .FND fonts are 16 pixels high. Therefore, the font is displayed from pixel 1 to pixel 16 of each screen row. CA-Clipper allows you to control the number of pixel rows to use for the font:
GFNTSET(aFont, nClipTop, nClipBottom)
Pass aFont as NIL if you only want to change the nClipTop and nClipBottom.
This feature provides the ability to display a one pixel frame around a GET or MENU PROMPT, etc. without having to use GWRITEAT(), because DevOut() (@..SAY..) is faster than GWRITEAT().
Using .FNT fonts: Be aware that .FNT fonts are proportional. For example, this means that the characters "m" and "i" will not be the same number of pixels in width.
To use .FNT fonts, load a FNT font into memory :
aFntFont := GFNTLOAD( "MyFnt.FNT" )
GWRITEAT( X, Y, cString, nColor, LLG_MODE_SET, aFont )
By passing LLG_MODE_NIL to GWRITEAT(), you can retrieve the width of the string to be displayed on screen (without displaying it).
nWidth will contain the # of pixels of the string:
nWidth := GWRITEAT( X , Y, cString, nColor, LLG_MODE_NIL, aFntFont)
nColumns will contain the # of columns:
nColumns := nWidth / 8.
Examples
■ This example loads a Font file called MyFont.FND:`
// Function ShowOneFont (cString)
LOCAL aFont
// Load a specific font file (MyFont.FND) into memory
aFont := GFNTLOAD("MyFont.FND")
// Display cString using the loaded font
GWRITEAT(X, Y, cString, nColor, LLG_MODE_SET, aFont)
// *Important*
// You must erase the font from memory if it is no longer
// needed.
// This is because CA-Clipper's VMM is unable to automatically
// free the memory occupied by aFont.
GFNTERASE(aFont)
RETURN
aFont represents the pointer to the VMM region where the .FND font is loaded. aFont would have been created with GFNTLOAD().
nClipTop and nClipBottom specify how many pixel rows to use when displaying standard text output. This provides the ability to display a one pixel frame around a GET.
Returns
GFNTSET() returns a two-element array containing font clipping information.
Description
GFNTSET() sets an already loaded font as active. When GFNTSET() is called, all subsequent DevOut() calls will use the new font. This means that you can use multiple .FND fonts at the same time. To go back to the standard ROM font, use GFNTSET( LLG_FNT_ROM ). You can also use an .FND font in a GWRITEAT() as shown in the following code:
aFndFont := GFNTLOAD("TestFnd.FND") nColor := 3 GWRITEAT(1, 1, "This is some text", nColor, LLG_MODE_SET, aFndFont)
GFNTSET() returns a two-element array containing font clipping information. The structure of this array is { nTopPixelRow, nBottomPixelRow }. This feature allows text to fit at a reduced height. A common requirement is to draw a frame around a GET without having to use a full text line over and under the GET. When you display a character with a DevOut() or a GET display method, the background always gets overwritten. So, if a frame is precisely drawn around the GET, part of the frame will be overwritten as soon as a single character is displayed.
In general, all regular fonts do not use the top and bottom row of pixels. This allows a displayed character to be clipped or restricted so that DevPos()/DISPLAY() will only erase the lines 1-14 (instead of 0- 15) and will preserve the frame previously drawn.
Examples
■ This example loads a font file called MyFont.FND:
FUNCTION ShowOneFont (cString)
LOCAL aFontBig, aFontSmall
// Load a couple of fonts into memory
aFontBig := GFNTLOAD("BigFnt.FND")
aFontSmall := GFNTLOAD("SmallFnt.FND")
// Set the BigFnt.FND to be active. As soon as
GFNTSET() is
// called, @...SAY, DevOut() etc. will use the new
font.
GFNTSET(aFontBig)
@1,1 SAY "This text should appear in the font 'BigFnt.FND'"
// Display something in a Big font
GWRITEAT(X , Y , "Using Big Font...", nColor, LLG_MODE_SET)
GWRITEAT(X , Y , "Using Small Font...", nColor, LLG_MODE_SET,;
aFontSmall)
// Set the SmallFnt.FND to be active
GFNTSET(aFontSmall)
// Display something in a Small font
GWRITEAT(X , Y , "Using Small Font...", nColor, G_MODE_SET)
// Use the standard ROM font
GFNTSET(G_FNT_ROM)
// Display something
GWRITEAT(X , Y , "Using ROM Font...", nColor, G_MODE_SET)
// *Important* You must erase the fonts from memory
// if it is no
// longer used. This is because CA-Clipper's VMM is
// unable to free
// the memory occupied by aFont
GFNTERASE(aFontBig)
GFNTERASE(aFontSmall)
RETURN NIL
nXStart, nYStart, nXEnd, and nYEnd define frame coordinates in pixels.
nColorBack is a numeric value representing the display color of the border background.
nColorLight is a numeric value representing the light display color for borders.
nColorDark is a numeric value representing the dark display color for borders.
The range of color values is limited to the number of colors available in the selected video mode. In 16-color modes, valid values are 0-15. In 256-color modes, valid values are 0-255.
nWidthUp is a numeric value representing the thickness of the frame borders. The values nWidthRight, nXStart, nYStart, nXEnd, nYEnd are the external dimensions nWidthDown of the frame, and the width of the borders is measured nWidthLeft within the rectangle.
nMode represents the frame mode. The following are valid nMode values:
Frame Mode Constants
Constant Description
LLG_MODE_SET Display in SET mode (ignores any pixels present under the
line displayed). This is the most common display mode.
LLG_MODE_AND Display in AND mode (executes an AND on pixels present
under the line at display time and on the display color).
LLG_MODE_OR Display in OR mode (executes an OR on pixels present
under the line at display time and on the display color).
LLG_MODE_XOR Display in XOR mode (executes an XOR on pixels present
under the line at display time and on the display color).
See note.
nStyle defines the style of the ellipse using one of the constants listed in the table below:
Style Mode Constants
Constant Description
LLG_FILL Fills the frame with nColorBack. This is the default.
LLG_FRAME Displays the frame in 3-D without filling in the frame with
nColorBack.
Note: This method allows you to move objects around on the screen without damaging the background. To retrieve the initial background, just repeat the call for display in XOR mode. If the display mode parameter is missing, the last mode specified in a call to a CA-Clipper function is used.
Returns
GFRAME() always returns NIL.
Description
GFRAME() draws box frames with a 3-D look using three appropriately selected colors. For example, gray for the background, black for the dark color and white for the light color. This function can be used only if you have set the screen to a graphic mode using GMODE(). This function respects the constraints defined by GSETCLIP().
Examples
■ This example shows how to display a series of frames with thin
borders (3 pixels):
Switch to graphic mode
SET VIDEOMODE TO LLG_VIDEO_VGA_640_480_16
// Buttons
GFRAME(0, 0, 53, 399, 7, 15, 8, 3, 3, 3, 3, LLG_MODE_SET)
// Coordinates
GFRAME(0, 400, 53, 456, 7, 15, 8, 3, 3, 3, 3, LLG_MODE_SET)
// Painting
GFRAME(54, 0, 639, 399, 7, 15, 8, 3, 3, 3, 3, LLG_MODE_SET)
// Palette
GFRAME(54, 400, 639, 456, 7, 15, 8, 3, 3, 3, 3, LLG_MODE_SET)
// Messages
GFRAME(0, 457, 639, 479, 7, 15, 8, 3, 3, 3, 3, LLG_MODE_SET)
QUIT // End of application
nX1, nY1, nX2, and nY2 define the line coordinates in pixels.
nColor is a numeric value representing the display color. If the parameter is missing, the last color specified in a call to a CA-Clipper function is used. The range of values is limited to the number of colors available in the selected video mode. In 16-color modes, valid values are between 0 and 15. In 256-color modes, valid values are between 0 and 255.
Display Mode Constants
Constant Description
LLG_MODE_SET Display in SET mode (ignores any pixels present under the
line displayed). This is the most common display mode.
LLG_MODE_AND Display in AND mode (executes an AND on pixels present
under the line at display time and on the display color).
LLG_MODE_OR Display in OR mode (executes an OR on pixels present
under the line at display time and on the display color).
LLG_MODE_XOR Display in XOR mode (executes an XOR on pixels present
under the line at display time and on the display color).
See note.
Note: This method allows you to move objects around on the screen without damaging the background. To retrieve the initial background, just repeat the call for display in XOR mode. If the display mode parameter is missing, the last mode specified in a call to a CA-Clipper graphic function is used.
Returns
GLINE() always returns NIL.
Description
GLINE() draws lines on the screen and respects the constraints defined by GSETCLIP(). This function can be used only if you have set the screen to a graphic mode using SET VIDEOMODE.
Examples
■ This example displays a line in a region restricted by
clipping:
// Switch to graphic mode
SET VIDEOMODE TO LLG_VIDEO_VGA_640_480_16
// Restrict the display region to a portion of the screen
GSETCLIP(100, 100, 300, 300)
// Draw a line using color 6
GLINE(0, 0, 400, 400, 6, LLG_MODE_SET)
QUIT // End of application
nMode is a numeric value that represents the video mode.
The following are valid nMode values. They are all #defines in Llibg.ch.
Video Mode Constants
Constant Description
LLG_VIDEO_TXT Switch to text mode
LLG_VIDEO_VGA_640_480_16 Switch to VGA 640x480x16 mode
LLG_VIDEO_VESA_800_592_16 Switch to VESA 800x592x16
LLG_VIDEO_VESA_1024_768_16 Switch to VESA 1024x768x16
LLG_VIDEO_VESA_1280_1024_16 Switch to VESA 1280x1024x16
LLG_VIDEO_VESA_640_480_256 Switch to VESA 640x480x256
LLG_VIDEO_VESA_800_592_256 Switch to VESA 800x592x256
LLG_VIDEO_VESA_1024_768_256 Switch to VESA 1024x768x256
LLG_VIDEO_VESA_1280_1024_256 Switch to VESA 1280x1024x256
Note: LLG_VIDEO_TEXT and LLG_VIDEO_VGA_640_480_16 are the only two video modes applicable to CA-Clipper.
You can precede nMode by a minus sign. Supplying a negative argument in this manner causes GMODE() to check if the specified mode is available without switching to that mode.
Returns
If the video mode is available, GMODE() will return an array containing the settings for the requested video mode. The following table shows the array structure:
aOldState Structure
Array Position Return Value
LLG_MODE_TEXT_ROW Numeric value representing the number of text
rows on screen.
LLG_MODE_TEXT_COL Numeric value representing the number of text
columns on screen.
LLG_MODE_GRAPH_ROW Numeric value representing the number of
graphic rows on screen.
LLG_MODE_GRAPH_COL Numeric value representing the number of
graphic columns on screen.
LLG_MODE_FONT_ROW Numeric value representing the number of
graphic rows per character.
LLG_MODE_FONT_COL Numeric value representing the number of
graphic columns per character.
LLG_MODE_COLOR_MAX Numeric value representing the number of
available colors.
LLG_MODE_IN_USE Numeric value representing the video mode that
was in use before calling GMODE(). See table
in the Arguments section.
LLG_MODE_LIB_VERSION Numeric value representing the version of the
LLIBG library.
LLG_MODE_LST_COLOR Numeric value representing the last color used
in a GXXX()function. This value will be used
in the next call to a GXXX() function if the
color parameter is not defined. The initial
value is 7.
LLG_MODE_LST_MODE Numeric value representing the last mode
(SET|AND|OR|XOR).
If nMode is omitted, GMODE() returns the current video mode settings.
Description
The GMODE() function is used to change the video mode or to retrieve information about the current video mode. CA-Clipper graphic mode supports the video modes described above. LLG_VIDEO_TEXT and LLG_VIDEO_VGA_640_480_16 are the only two video modes applicable to CA-Clipper. You can switch between modes at any time in your application. To switch to regular text mode use GMODE(LLG_VIDEO_TXT). The video will not change if GMODE() is called without parameters. GMODE() will return the current video mode information only.
When switching from LLG_VIDEO_TXT to LLG_VIDEO_VGA_640_480_16 mode, all displayed text lines are converted to the equivalent graphic mode display. This conversion does not happen when switching back to text mode. If you need an application to start in graphic mode with an empty screen, call CLS before calling GMODE (LLG_VIDEO_VGA_640_480_16).
Important! To switch video modes, the SET VIDEOMODE command must be used. Without this command, the video mode may not be switched properly.
Notes
During video mode switching, the library calls CA-Clipper's SetMode() function with 25,80 as parameters. If you use other values, the call to GMODE() should be followed with a call to SETMODE (nYourRow,nYourCol).
In graphic mode, you have access to all available screen lines and columns. Any call to SetMode() with a number of lines less than or equal to 30 causes CA-Clipper graphic mode to use a 16-pixel font that yields 30 lines.
For example, if you call SETMODE (25,80) with a font that is 8 pixels wide by 16 pixels high, and switch video mode to LLG_VIDEO_VGA_640_480_16, the same font is used. You get an additional 5 rows of text to the specified 25 i.e.,(480/16) = 30 rows of text!
CA-Clipper uses the following chart for calculating font sizes based on video settings:
SetMode(nRow, nColumn) Calculation Chart
nRow Fonts Number of Rows Available
31- 34 14-pixel font 34
43 See note below
60+ 8-pixel font 60
Note: The 43-line mode being an EGA emulation of a VGA card, is not available in 640 x 480 x 16 mode.
The following are the available settings:
Available Settings
Wide / High Pixels Column / Row
640 x 480 80 x 30 or 80 x 60
800 x 592 100 x 37 or 100 x 74
1024 x 768 128 x 48 or 100 x 96
1280 x 1024 160 x 64 or 160 x 128
During the execution of a QUIT or on the last RETURN of your application, the application is automatically set back to the starting video mode, which is usually text mode.
Note: CA-Clipper uses the ROM fonts of your VGA video card. This allows you to speed up text display. It guarantees zero use of main memory since no font loading is required, even in graphic mode. You can also avoid having to provide one or more font files with the .EXE.
Examples
■ This example executes an entire application in graphic mode:
// Switch to graphic mode
SET VIDEOMODE TO LLG_MODE_VGA_640_480_16
// This is equivalent to GMODE (LLG_VIDEO_VGA_640_480_16)
// Your CA-Clipper instructions will now operate
// in graphic mode!
.
.
.
QUIT // End of application
■ This example stores the graphic mode parameters in variables
which can be used later on in an application:
// Switch to graphic mode and save the current graphic mode
// settings
SET VIDEOMODE TO LLG_MODE_VGA_640_480_16
aMode := GMODE()
// Store the different values
nTxtRow := aMode[LLG_MODE_TEXT_ROW]
nTxtCol := aMode[LLG_MODE_TEXT_COL]
nGraRow := aMode[LLG_MODE_GRAPH_ROW]
nGraCol := aMode[LLG_MODE_GRAPH_COL]
nFonRow := aMode[LLG_MODE_FONT_ROW]
nFonCol := aMode[LLG_MODE_FONT_COL]
nColorMax := aMode[LLG_MODE_COLOR_MAX]
nVideoMode := aMode[LLG_MODE_IN_USE]
nLibVer := aMode[LLG_MODE_LIB_VERSION]
nLstColor := aMode[LLG_MODE_LST_COLOR]
nLstMode := aMode[LLG_MODE_LST_MODE]
■ This example creates two pseudo-functions which return the
number of lines and columns in pixels, similar to the way MaxRow()
and MaxCol() return line and column values:
#translate GMAXROW() => GMODE()[LLG_MODE_GRAPH_ROW]
#translate GMAXCOL() => GMODE()[LLG_MODE_GRAPH_COL]
■ This is a similar function that returns the number of colors
available:
#translate GMAXCOLOR() => GMODE()[LLG_MODE_COLOR_MAX]
xIdentity is a unique value guaranteed by the structure of the data file to reference a specific item in a data source (database). In a .dbf, identity is the record number. In other data formats, identity is the unique primary key value.
BOTTOM specifies the last logical record in the current work area.
TOP specifies the first logical record in the current work area.
Description
GO[TO] is a database command that positions the record pointer in the current work area at the specified identity. In an Xbase data structure, this identity is the record number because every record, even an empty record, has a record number. In data structures of different design, identity may be defined as something other than record number.
Examples
■ This example saves the current record number, searches for a
key, and then restores the record pointer to the saved position:
FUNCTION KeyExists( xKeyExpr )
LOCAL nSavRecord := RecNo() // Save the current record
// pointer position
LOCAL lFound
SEEK xKeyExpr
IF ( lFound := Found() )
.
. < statements >
.
ENDIF
GOTO nSavRecord // Restore the record pointer position
RETURN ( lFound )
aVertex is an array value representing an array of polygon vertices coordinates.
lFilled is a logical value that creates a filled or non-filled polygon. LLG_FILL or LLG_FRAME are valid constants.
nMode is a numeric value representing the video Mode. The following are valid nMode values. They are all # defines in Llibg.ch.
Display Mode Constants
Constant Description
LLG_MODE_SET Display in SET mode (ignores any pixels present under the
line displayed). This is the most common display mode.
LLG_MODE_AND Display in AND mode (executes an AND on pixels present
under the line at display time and on the display color).
LLG_MODE_OR Display in OR mode (executes an OR on pixels present
under the line at display time and on the display color).
LLG_MODE_XOR Display in XOR mode (executes an XOR on pixels present
under the line at display time and on the display color).
See note.
Note: This method allows you to move objects around on the screen without damaging the background. To retrieve the initial background, just repeat the call for display in XOR mode. If the display mode parameter is missing, the last mode specified in a call to a CA-Clipper graphic function is used.
nOutLine is a numeric value representing the outline color.
nFillColor is a numeric value representing the fill color.
Returns
GPOLYGON() always returns NIL.
Description
GPOLYGON() can be used to create a polygon. Simply pass an array of coordinates which make up the polygon.
Examples
■ The following array of vertices would draw a triangle:
aVertex := {{1,5},; // First point
{20,45},; // Second point
{65,145} ; // Third point}
Platforms
Available on MS-DOS
File
Library is LLIBG.LIB, the header file is Llibg.ch.
nX and nY define pixel coordinates for row and column on the screen.
nColor is a numeric value representing the display color of the pixel.
The range of values is limited to the number of colors available in the selected video mode. In 16-color modes, valid values are between 0 and 15. In 256-color modes, valid values are between 0 and 255.
nMode is the numeric value representing the video mode. The following are valid nMode values. They are all # defines in Llibg.ch.
Video Mode Constants
Constant Description
LLG_MODE_SET Display in SET mode (ignores any pixels present under the
line displayed). This is the most common display mode.
LLG_MODE_AND Display in AND mode (executes an AND on pixels present
under the line at display time and on the display color).
LLG_MODE_OR Display in OR mode (executes an OR on pixels present
under the line at display time and on the display color).
LLG_MODE_XOR Display in XOR mode (executes an XOR on pixels present
under the line at display time and on the display color).
See note.
Note: This method allows you to move objects around on the screen without damaging the background. To retrieve the initial background, just repeat the call for display in XOR mode. If the display mode parameter is missing, the last mode specified in a call to a CA-Clipper graphic function is used.
Returns
GPUTPIXEL() always returns NIL.
Description
This function can be used to change the color of a specific pixel on the screen.
Examples
■ The following example will put a white pixel at X-coordinate
200 and Y-coordinate 100:
GPUTPIXEL (200, 100, 15, LLG_MODE_SET)
nXStart, nYStart, nXEnd and nYEnd define the rectangle coordinates in pixels.
nStyle defines the style of the rectangle using one of the constants listed in the table below:
Style Mode Constants
Constant Description
LLG_FILL The rectangle is displayed first and then it is filled with
the color and mode specified below
LLG_FRAME Display of the rectangle is restricted to its contour in
the color and mode specified below
nColor is a numeric value that represents the display color. If this parameter is missing, the last color specified in a call to a CA-Clipper graphic function is used. The value range of values is limited to the number of colors available in the selected video mode. In 16-color modes, valid values are between 0 and 15. In 256-color modes, valid values are between 0 and 255.
nMode represents the display mode. The following are valid nMode values:
Display Mode Constants
Constant Description
LLG_MODE_SET Display in SET mode (ignores any pixels present under the
line displayed). This is the most common display mode.
LLG_MODE_AND Display in AND mode (executes an AND on pixels present
under the line at display time and on the display color).
LLG_MODE_OR Display in OR mode (executes an OR on pixels present
under the line at display time and on the display color).
LLG_MODE_XOR Display in XOR mode (executes an XOR on pixels present
under the line at display time and on the display color).
See note.
Note: This method allows you to move objects around on the screen without damaging the background. To retrieve the initial background, just repeat the call for display in XOR mode. If the display mode parameter is missing, the last mode specified in a call to a CA-Clipper graphic function is used.
Returns
GRECT() always returns NIL.
Description
GRECT() draws filled or empty rectangles on the screen. This function can be used only if you have set the screen to a graphic mode using GMODE(). It respects the constraints defined by GSETCLIP().
Examples
■ This example shows how to display a rectangle in a region
restricted by clipping:
// Switch to graphic mode
SET VIDEOMODE LLG_VIDEO_VGA_640_480_16)
// Restrict the display region to one portion of the screen
GSETCLIP(100,100,300,300)
// Draw a filled rectangle that is partially clipped
GRECT(120,120,350,350,LG_FILL,2,LLG_MODE_SET)
QUIT // End of application
nX1 is a numeric value representing the left X-axis (column) position of the region in pixels.
nY1 is a numeric value representing the top Y-axis (row) position of the region in pixels.
nX2 is a numeric value representing the right X-axis (column) position of the region in pixels.
nY2 is a numeric value representing the bottom Y-axis (row) position of the region in pixels.
Either all parameters should be specified or none.
Returns
GSETCLIP() returns an array of four numbers representing the new clipping region if you specify all arguments, and the current region if you specify none.
Description
GSETCLIP() limits the active display to a portion of the screen. This function applies only to CA-Clipper graphic mode functions beginning with "G", such as GRECT(), GLINE(), GBMPDISP(). Text emulation functions such as DevOut() and QOut() are not affected by setting clipping regions. To enhance redraw speed, clipping of the function for rewriting text in GWRITEAT() graphic mode is simplified. CA-Clipper graphic mode checks whether each character displayed fits entirely in the clipping region. If it does, the character is displayed; otherwise, it is not.
Notes
The clipping region is initialized to be the entire screen. To specify maximum clipping (which amounts to eliminating clipping altogether), you need to pass parameters to GSETCLIP() corresponding to the entire screen. There are two ways to do this:
■ Save the clipping state immediately after the change. This is
equivalent to the whole screen at that instant:
SET VIDEOMODE TO LLG_VIDEO_VGA_640_480_16 // Retrieve clipping value aMaxClip := GSETCLIP() // Execute clipping GSETCLIP(nCoord list) . . . // Your code . . . // Retrieve clipping value GSETCLIP(aMaxClip[1] , aMaxClip[2] , aMaxClip[3] , aMaxClip[4])
■ Use GMODE() which returns the screen size in pixels:
// Switch to graphic mode SET VIDEOMODE TOLLG_VIDEO_VGA_640_480_16
■ This example restricts display to a portion of the screen:
// Switch to graphic mode
SET VIDEOMODE TO LLG_VIDEO_VGA_640_480_16
// Restrict the display region
GSETCLIP(100, 100, 300, 300)
DO WHILE ! (Inkey() == K_ESC)
AreaDraw() // Call a drawing function
ENDDO
QUIT // End of application
■ This example stores clipping region parameters for later use:
// Switch to graphic mode
SET VIDEOMODE TO LLG_VIDEO_VGA_640_480_16
// Retrieve current values
aOldRegion := GSETCLIP()
// Restrict display region to a portion of the screen
GSETCLIP(100,100,300,300)
DO WHILE !(Inkey() == K_ESC)
AreaDraw()
// Call a function that draws something
ENDDO
// Reset original clipping regions
GSETCLIP(aOldRegion[1],;
aOldRegion[2],;
aOldRegion[3],;
aOldRegion[4])
QUIT // End of application
nExclArea is a numeric value representing the exclusion area number.
nTop, nLeft, nBottom, nRight, and nType define the exclusion area coordinates.
Coordinate Type Constants
Constant Description
LLM_COOR_TEXT <nTop> which is the default, is the row line number.
LLM_COOR_GRAPH <nTop> is the row in pixels.
Note: Either zero, nExclArea, or all other parameters should be specified.
Returns
If nExclArea is specified, an array of exclusion area coordinates for nExclArea is returned. GSETEXCL(LLG_EXCL_KILL_ALL) deletes all previously defined exclusion areas. If no arguments are specified, GSETEXCL() returns the number of active exclusion areas. If nTop, nLeft, nBottom, nRight,and nType are specified, NIL is returned.
Description
This function is used to prevent output from being displayed in a defined region of the screen. The GSETEXCL() function is probably the most complex function in CA-Clipper graphic mode. If you have never used the DispBegin() and DispEnd() functions, please read CA-Clipper's documentation for further explanation of these two functions. Essentially, these functions are used to trap or "buffer" all screen output. DispBegin() initiates the buffering and DispEnd() stops the buffering and updates the screen.
GSETEXCL() is the opposite of GSETCLIP(). GSETEXCL() and GSETCLIP() must never be used at the same time. A call to GSETCLIP() will destroy all previously defined exclusion areas. CA-Clipper internally maintains exclusion areas as if they were multiple inclusion areas.
To understand GSETEXCL(), imagine a cascading window system with three windows, A, B and C:
Our goal is to display information in window A while it is covered by windows B and C.
■ Old text mode technique: Using CA-Clipper in text mode and
assuming you saved each window region prior to painting the window boxes, you would probably do the following:
1. Issue a DispBegin() to activate video buffering.
2. Pop off each screen by individually saving the current screens
and immediately restoring that window's previous background, starting with window C, and then doing window B. For example,
5. Issue a DispEnd() because up to now the user has not seen any
screen activity since every screen output function has been buffered!
By issuing a DispEnd(), ALL of the buffered data is instantly flushed to the screen. Essentially the user sees only the final screen and not the intermediate screen activity along the way. The user is not aware of the displaying and redisplaying of windows B and C. This provides a smooth visual effect. This buffering method is available in text mode because display orders are fast, simple and the memory needed to save a full screen is small (4KB).
■ New graphic mode technique: The situation is totally
different in graphic mode. DispBegin() and DispEnd() are not enabled in CA-Clipper graphic mode. CA-Clipper uses exclusion areas instead of removing windows until we have the desired window current. This exclusion area concept is used in almost every graphical system, including Microsoft Windows. An exclusion area is simply a defined screen region which is prevented from having data written to it.
In the example above, you would declare windows B and C as exclusion areas. This prevents data from being written to these windows. Therefore, when you modify information in window A, windows B and C are not affected. The above example using exclusion areas would be as follows:
GSETEXCL(nTop, nLeft, nBottom, nRight) // Window B coordinates GSETEXCL(nTop, nLeft, nBottom, nRight) // Window C coordinates // Manipulate or paint information in window A. GSETEXCL (LLG_EXCL_KILL_ALL)
Notes
You must reset the exclusion areas once the screen work is completed; otherwise, the exclusion areas remain active. This essentially prevents any data from ever being written to those screen regions. As you can see, DispBegin() and DispEnd() require a lot of work to manage a simple cascade of windows, and the overhead in graphic mode renders the technique unusable. Exclusion zones do not consume memory, are faster, and are simpler to use.
nColor is a numeric value that represents a display color.
The range of values for the parameter is limited to the number of colors available in the selected video mode. In 16-color modes, valid values are between 0 and 15. In 256-color modes, valid values are between 0 and 255.
nRedValue is a numeric value that represents the red component assigned to nColor. Its possible values are from 0 to 63.
nGreenValue is a numeric value that represents the green component assigned to nColor. Its possible values are from 0 to 63.
nBlueValue is a numeric value that represents the blue component assigned to nColor. Its possible values are from 0 to 63.
aFullOldPalette is an array of components in the palette. The structure of the array is { nRedValue, nGreenValue, nBlueValue }.
aRGB is an array of components in the palette. The structure of the array is { nRedValue, nGreenValue, nBlueValue }.
Returns
aOldPalette represents an array of components in palette:
The GSETPAL() function changes a color's basic component values. This function must be called for each color if you want to change the palette. It can be used in text or graphic mode.
Notes
CA-Clipper saves the VGA|VESA environment including the palette. It also saves the first call to GMODE() or SET VIDEOMODE. When you do a QUIT or reach the last RETURN of your application, your initial video mode is automatically restored. You do not need to save the original color palette.
Examples
■ This example stores a video mode's color components in a
multidimensional array. It is identical to calling GSETPAL() with no
parameters:
FUNCTION aPalSave()
LOCAL aPalStore := {}
LOCAL nI := 0
// For all colors in the current video mode
FOR nI := 1 TO GMODE()[LLG_MODE_COLOR_MAX]
// Save color reference and color components
AAdd(aPalStore, {nI-1,;
GSETPAL(nI-1)[1],;
GSETPAL(nI-1)[2],;
GSETPAL(nI-1)[3]})
NEXT nI
// Return an array of arrays
RETURN aPalStore
■ This example loads all color components of a video mode using
a multidimensional array which contains the individual components:
FUNCTION aPalRest(aPalette)
LOCAL nI := 0
// For all the arrays in the major array
FOR nI := 1 TO Len(aPalette)
// Reset the color components
GSETPAL(aPalette[nI,1],;
aPalette[nI,2],;
aPalette[nI,3],;
aPalette[nI,4];)
NEXT nI
RETURN aPalette
nColStart and nLnStart define graphic text coordinates in pixels.
cStringis a character value representing the character string to be displayed.
nColoris a numeric value representing the display color. If the parameter is missing, the last color specified in a call to a CA-Clipper graphic function is used.
The range of values is limited to the number of colors available in the selected video mode. In 16-color modes, valid values are between 0 and 15. In 256-color modes, valid values are between 0 and 255.
nMode is a numeric value representing the display mode. The following are valid nMode values. They are all #defines in Llibg.ch.Display color
Display Mode Constants
Constant Description
LLG_MODE_SET Display in SET mode (ignores any pixels present under the
line displayed). This is the most common display mode.
LLG_MODE_AND Display in AND mode (executes an AND on pixels present
under the line at display time and on the display color).
LLG_MODE_OR Display in OR mode (executes an OR on pixels present
under the line at display time and on the display color).
LLG_MODE_XOR Display in XOR mode (executes an XOR on pixels present
under the line at display time and on the display color).
See note.
LLG_MODE_NIL Allows you to compute the width of the string without
displaying anything on the screen. Be aware that .FNT
fonts are proportional, which means that an "m" and an
"i" do not use the same number of pixels.
Note: This method allows you to move objects around on the screen without damaging the background. To retrieve the initial background, just repeat the call for display in XOR mode. If the display mode parameter is missing, the last mode specified in a call to a CA-Clipper graphic function is used.
aFont is an optional font array pointer which was created with the GFNTLOAD("MyFont.FND") function:
FUNCTION ShowOneFont (cString)
LOCAL aFont // Load a specific font file into memory aFont := GFNTLOAD("MyFont.FND") // Display cString using the loaded font
GWRITEAT(X , Y , cString, nColor, LLG_MODE_SET, aFont) // Important // You must erase the font if it is no longer used. GFNTERASE(aFont) RETURN NIL
Returns
GWRITEAT() returns the width of the written text in pixels.
Description
GWRITEAT() displays text in graphic mode without affecting the background. It is important not to confuse the functions DevOut() and GWRITEAT(). Even when you are in graphic mode, you should continue to use DevPos(), DevOut(), and QOut() for all "normal" displays. The functions related to GETs, TBROWSE, etc. use both foreground and background colors, and text can only be displayed in areas whose size is a multiple of the selected font size.
Notes
GWRITEAT() should be used for graphic enhancements, such as a window title within its frame (as you do not want to overwrite the window frame's borders), or to display information in graphic areas where you want to explicitly handle whether or not the background is erased before a new display, as in adding a title to a bitmap.
Unlike DevOut(), this function receives graphic coordinates only. This allows you to display text pixel by pixel. Since GWRITEAT() works with pixel coordinates instead of row and column coordinates, you may need to properly calculate nX and nY. This function can be used only if you have set the screen to a graphic mode using SETVIDEOMODE().
This function respects the constraints defined by GSETCLIP().
Examples
■ This example writes a see-through title on the frame of a 3-D
box:
// Switch to graphic mode
SET VIDEOMODE TO LLG_VIDEO_VGA_640_480_16
// Display a 3D box of constant width 16x16x16x16
DispBox(nTop, nLeft, nBottom, nRight, LLG_BOX_GRAY_SQUARE)
// Write the alias name transparently in the 3D frame
GWRITEAT( nLeft * GMODE()[LLG_MODE_FONT_COL],;
nTop * GMODE()[LLG_MODE_FONT_ROW],;
Alias(Select()),;
4,;
LLG_MODE_SET)
QUIT // End of application
Replace all soft carriage returns in a character string with hard carriage returns
Syntax
HardCR(<cString>) → cConvertedString
Arguments
cString is the character string or memo field to be converted.
Returns
HardCR() returns a character string up to 65,535 (64K) characters in length.
Description
HardCR() is a memo function that replaces all soft carriage returns (Chr(141)) with hard carriage returns (Chr(13)). It is used to display long character strings and memo fields containing soft carriage returns with console commands. In CA-Clipper, console commands (including REPORT and LABEL FORM) do not automatically convert soft carriage returns to hard carriage returns, making it necessary for you to explicitly make the conversion. Soft carriage returns are added by MemoEdit() when lines wrap.
Notes
■ HardCR() in REPORT and LABEL FORMs: If HardCR() is used in a
REPORT FORM or LABEL FORM contents expression and nowhere else, you must declare it EXTERNAL to ensure that it is linked.
■ HardCR() does not remove a soft carriage return if it is
specified alone (i.e. HARDCR (Chr(141) ). It requires the combination of a soft carriage return and a line feed, i.e., Chr(141) + Chr(10).
Examples
■ To display a memo field formatted with the automatic word
wrapping of MemoEdit():
USE Sales NEW
? HardCR(Sales->Notes)
Header() returns the number of bytes in the header of the current database file as an integer numeric value. If no database file is in use, Header() returns a zero (0).
Description
Header() is a database function that is used with LastRec(), RecSize(), and DiskSpace() to create procedures for backing up files.
By default, Header() operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression (see example below).
Examples
■ This example determines the header size of Sales.dbf:
USE Sales NEW
? Header() // Result: 258
■ This example defines a pseudofunction, DbfSize(), that uses
Header() with RecSize() and LastRec() to calculate the size of the
current database file in bytes:
#define DbfSize() ((RecSize() * LastRec()) + ;
Header() + 1)
Later you can use DbfSize() as you would any function:
USE Sales NEW
USE Customer NEW
? DbfSize()
? Sales->(DbfSize())
Convert a CA-Clipper numeric to a 16-bit binary integer
Syntax
I2Bin(<nInteger>) → cBinaryInteger
Arguments
nInteger is an integer numeric value to be converted. Decimal digits are truncated.
Returns
I2Bin() returns a two-byte character string containing a 16-bit binary integer.
Description
I2Bin() is a low-level file function that converts an integer numeric value to a character string formatted as a binary integer—least significant byte first. I2Bin() is used with FWrite() to convert a CA-Clipper numeric to a standard binary form. The inverse of I2Bin() is Bin2I().
Examples
■ This example opens a database file using low-level file
functions and writes a new date of the last update to bytes 1-3:
#include "Fileio.ch"
//
nHandle = FOpen("Sales.dbf", FO_READWRITE)
//
// Convert date of last update to int
nYear = I2Bin(90)
nMonth = I2Bin(12)
nDay = I2Bin(15)
//
// Point to the date of last update
FSeek(nHandle, 1, FS_SET)
//
// Write the new update date using only the first byte
FWrite(nHandle, nYear, 1)
FWrite(nHandle, nMonth, 1)
FWrite(nHandle, nDay, 1)
FClose(nHandle)
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/EXAMPLEA.ASM.
Execute one of several alternative blocks of statements
Syntax
IF <lCondition1>
<statements>...
[ELSEIF <lCondition2>]
<statements>...
[ELSE]
<statements>...
END[IF]
Arguments
lCondition is a logical control expression. If it evaluates to true (.T.), all following statements are executed until an ELSEIF, ELSE, or ENDIF is encountered.
ELSEIFlCondition identifies statements to execute if the associated condition evaluates to true (.T.) and all preceding IF or ELSEIF conditions evaluate to false (.F.). Any number of ELSEIF statements can be specified within the same IF...ENDIF control structure.
ELSE identifies statements to execute if the IF and all preceding ELSEIF conditions evaluate to false (.F.).
Description
The IF control structure works by branching execution to statements following the first true (.T.) evaluation of the IF or any ELSEIF condition. Execution then continues until the next ELSEIF, ELSE, or ENDIF is encountered whereupon execution branches to the first statement following the ENDIF.
If no condition evaluates to true (.T.), control passes to the first statement following the ELSE statement. If an ELSE statement is not specified, control branches to the first statement following the ENDIF statement.
IF...ENDIF structures may be nested within IF...ENDIF structures and other control structure commands. These structures, however, must be nested properly.
The IF...ELSEIF...ENDIF form of the IF construct is identical to DO CASE...ENDCASE. There is no specific advantage of one syntax over the other. The IF construct is also similar to the IF() function which can be used within expressions.
Examples
■ This example evaluates a number of conditions using an
IF...ELSEIF...ENDIF construct:
LOCAL nNumber := 0
//
IF nNumber < 50
? "Less than 50"
ELSEIF nNumber = 50
? "Is equal to 50"
ELSE
? "Greater than 50"
ENDIF
Return the result of an expression based on a condition
Syntax
IF(<lCondition>, <expTrue>, <expFalse>) → Value
Arguments
lCondition is a logical expression to be evaluated.
expTrue is the value, a condition-expression, of any data type, returned if lCondition is true (.T.).
expFalse is the value, of any date type, returned if lCondition is false (.F.). This argument need not be the same data type as expTrue.
Returns
IF() returns the evaluation of expTrue if lCondition evaluates to true (.T.) and expFalse if it evaluates to false (.F.). The value returned is the data type of the valid condition-expression.
Description
IF() is a logical conversion function. It is one of the most powerful and versatile functions in CA-Clipper. It provides a mechanism to evaluate a condition within an expression. With this ability you can convert a logical expression to another data type.
Examples
■ This example converts a logical data value to a numeric data
value:
lPaid = .T.
? IF(lPaid, 1, 0) // Result: 1
■ In this example a logical field is formatted depending on
whether the Customer is past due or not:
@ Row() + 1, 25 SAY IF(lPaid, Space(10), "Go get 'em")
■ If you are printing forms, you can print an indicating symbol
in different columns depending on the value of a logical field:
@ Row(), IF(InHospital, 10, 12) SAY "X"
■ You can also use IF() to force the LABEL FORM to print blank
lines. Enter the following expression when you create the label with
RL.EXE:
IF(Empty(Company), Chr(255), Company)
Return the result of an expression based on a condition
Syntax
[I]IF(<lCondition>, <expTrue>, <expFalse>) → Value
Arguments
lCondition is a logical expression to be evaluated.
expTrue is the value, a condition-expression, of any data type, returned if lCondition is true (.T.).
expFalse is the value, of any date type, returned if lCondition is false (.F.). This argument need not be the same data type as expTrue.
Returns
IIF() returns the evaluation of expTrue if lCondition evaluates to true (.T.) and expFalse if it evaluates to false (.F.). The value returned is the data type of the valid condition-expression.
Description
IIF() is a logical conversion function. It is one of the most powerful and versatile functions in CA-Clipper. It provides a mechanism to evaluate a condition within an expression. With this ability you can convert a logical expression to another data type.
Examples
■ This example converts a logical data value to a numeric data
value:
lPaid = .T.
? IIF(lPaid, 1, 0) // Result: 1
■ In this example a logical field is formatted depending on
whether the Customer is past due or not:
@ Row() + 1, 25 SAY IIF(lPaid, Space(10), "Go get 'em")
■ If you are printing forms, you can print an indicating symbol
in different columns depending on the value of a logical field:
@ Row(), IIF(InHospital, 10, 12) SAY "X"
■ You can also use IIF() to force the LABEL FORM to print blank
lines. Enter the following expression when you create the label with
RL.EXE:
IIF(Empty(Company), Chr(255), Company)
Return the default index extension based on the database driver currently linked
Syntax
IndexExt() → cExtension
Returns
Unless you have linked another database driver, IndexExt() returns ".ntx" to indicate that the default CA-Clipper driver is in effect. If the dBASE III PLUS compatible database driver is linked, the function returns ".ndx".
Description
IndexExt() returns the default index file extension by determining which database driver is currently linked. Note that it is preferable to use ordBagExt() than IndexExt().
Notes
■ IndexExt() returns the default index extension of the
driver loaded, not the actual index file extension. If no driver is loaded, ".ntx" is returned.
Examples
■ In this example, IndexExt() creates an existence test for the
Customer index file independent of the database driver linked into
the current program:
USE Customer NEW
//
IF .NOT. FILE("Customer" + IndexExt())
INDEX ON CustName TO Customer
ENDIF
nOrder is the ordinal position of the index in the list of index files opened by the last USE...INDEX or SET INDEX TO command for the current work area. A zero value specifies the controlling index, without regard to its actual position in the list.
Returns
IndexKey() returns the key expression of the specified index as a character string. If there is no corresponding index or if no database file is open, IndexKey() returns a null string ("").
Description
IndexKey() is a database function that determines the key expression of a specified index in the current work area and returns it as a character string. To evaluate the key expression, specify IndexKey() as a macro expression like this: &(IndexKey(nOrder)).
IndexKey() has a number of applications, but two specific instances are important. Using IndexKey(), you can TOTAL on the key expression of the controlling index without having to specify the key expression in the source code. The other instance occurs within a dbEdit() user function. Here, you may want to determine whether or not to update the screen after the user has edited a record. Generally, it is only necessary to update the screen if the key expression of the controlling index has changed for the current record. Both of these examples are illustrated below.
By default, IndexKey() operates on the currently selected work area. It can be made to operate on an unselected work area by specifying it within an aliased expression (see example below).
Examples
■ This example accesses the key expression of open indexes in
the current work area:
#define ORD_NATURAL 0
#define ORD_NAME 1
#define ORD_SERIAL 2
//
USE Customer INDEX Name, Serial NEW
SET ORDER TO ORD_SERIAL
? IndexKey(ORD_NAME) // Result: Name index exp
? IndexKey(ORD_SERIAL) // Result: Serial index exp
? IndexKey(ORD_NATURAL) // Result: Serial index exp
■ This example accesses the key expression of the controlling
index in an unselected work area:
USE Customer INDEX Name, Serial NEW
USE Sales INDEX Salesman NEW
? IndexKey(0), Customer->(IndexKey(0))
■ This example uses IndexKey() as part of a TOTAL ON key
expression. Notice that IndexKey() is specified using a macro
expression to force evaluation of the expression:
USE Sales INDEX Salesman NEW
TOTAL ON &(IndexKey(0)) FIELDS SaleAmount TO ;
SalesSummary
■ This example uses IndexKey() to determine whether the dbEdit()
screen should be updated after the user has edited the current field
value. Generally, you must update the dbEdit() screen if the user
changes a field that is part of the controlling index key.
FieldEdit() is a user-defined function called from a dbEdit() user
function to edit the current field if the user has pressed an edit
key.
#include "Dbedit.ch"
#define ORD_NATURAL 0
FUNCTION FieldEdit()
LOCAL indexVal
// Save current key expression and value
indexVal = &(IndexKey(ORD_NATURAL))
.
. <code to GET current field value>
.
// Refresh screen if key value has changed
IF indexVal != &(IndexKey(ORD_NATURAL))
nRequest = DE_REFRESH
ELSE
nRequest = DE_CONT
ENDIF
RETURN nRequest
Return the order position of the controlling index
Syntax
IndexOrd() → nOrder
Returns
IndexOrd() returns an integer numeric value. The value returned is equal to the position of the controlling index in the list of open indexes for the current work area. A value of zero indicates that there is no controlling index and records are being accessed in natural order. If no database file is open, IndexOrd() will also return a zero.
Description
IndexOrd() is a database function that determines the position of the controlling index in the list of index files opened by the last USE...INDEX or SET INDEX TO in the current work area. It is often useful to save the last controlling index so it can be restored later.
By default, IndexOrd() operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression (see example below).
Examples
■ This example uses IndexOrd() to save the current order. After
changing to a new order, it uses the saved value to restore the
original order:
USE Customer INDEX Name, Serial NEW
nOrder := IndexOrd() // Result: 1
SET ORDER TO 2
? IndexOrd() // Result: 2
SET ORDER TO nOrder
? IndexOrd() // Result: 1
■ This example uses an aliased expression to determine the order
number of the controlling index in an unselected work area:
USE Sales INDEX Salesman, CustNum NEW
USE Customer INDEX Name, Serial NEW
? Sales->(IndexOrd()) // Result: 1
Extract a character from the keyboard buffer or a mouse event
Syntax
Inkey([<nSeconds>] [,<nEventMask>]) → nInkeyCode
Arguments
nSeconds specifies the number of seconds Inkey() waits for a keypress or mouse event. You can specify the value in increments as small as one-tenth of a second. Specifying zero halts the program until a key is pressed or an unmasked event occurs. If nSeconds is omitted, Inkey() does not wait for a keypress or mouse event.
nEventMask specifies which events should be returned. If nEventMask is omitted, the value represented by the SET EVENTMASK command will be used. If there is no SET EVENTMASK command issued, the default value that will be used is 128 (keyboard events only).
This parameter can be any combination of the following values. The constant values listed below are defined in inkey.ch.
Inkey Constants
Constant Value Descripiton
INKEY_MOVE 1 Mouse Events
INKEY_LDOWN 2 Mouse Left Click Down
INKEY_LUP 4 Mouse Left Click Up
INKEY_RDOWN 8 Mouse Right Click Down
INKEY_RUP 16 Mouse Right Click Up
INKEY_KEYBOARD 128 Keyboard Events
INKEY_ALL 159 All Mouse and Keyboard Events
Returns
Inkey() returns an integer value from -39 to 386 for keyboard events and integer values from 1001 to 1007 for mouse events. This value identifies either the key extracted from the keyboard buffer or the mouse event that last occurred. If the keyboard buffer is empty, and no mouse events are taking place, Inkey() returns 0. Inkey() returns values for all ASCII characters, function, Alt+Function, Ctrl+Function, Alt+Letter, and Ctrl+Letter key combinations.
Description
Inkey() is a keyboard function that extracts the next key pending in the keyboard buffer or the next mouse event and returns a value representing the appropriate event. The value is also saved internally and can be accessed using LastKey(). If the nSeconds argument is specified and there are no pending keys in the buffer, program execution pauses until a key appears in the keyboard buffer, or an appropriate mouse event occurs, or nSeconds has elapsed. The time Inkey() waits is based on the operating system clock and is not related to the microprocessor speed. If nSeconds is zero, program execution pauses until a key is pressed or an unmasked mouse event occurs. Note that Inkey() is not a wait state and, therefore, SET KEYs are not active.
Inkey() is similar to the NextKey() function. Unlike Inkey(), however, NextKey() reads, but does not extract the key or mouse event. This is useful when you need to test for a key or mouse event without processing it.
Inkey() is the basic primitive of the CA-Clipper system for fetching keys and mouse events. It is used for polling the keyboard, polling the mouse, or pausing program execution. As an example, you can use Inkey() to terminate commands with a record scope such as LIST, LABEL FORM, and REPORT FORM by including it in a WHILE condition.
Examples
■ The following example will inform Inkey() to terminate if the
left mouse button has been clicked or the right mouse button has been
clicked. If no events of this type occur within 10 seconds, Inkey()
will terminate.
? Inkey( 10 , INKEY_LDOWN + INKEY_RDOWN )
INDEX ON <expKey> [TAG <cOrderName>] [TO <cOrderBagName>]
[FOR <lCondition>] [ALL]
[WHILE <lCondition>] [NEXT <nNumber>]
[RECORD <nRecord>] [REST]
[EVAL <bBlock>] [EVERY <nInterval>]
[UNIQUE] [ASCENDING|DESCENDING]
[USECURRENT] [ADDITIVE]
[CUSTOM] [NOOPTIMIZE]
Note: Although both the TAG and the TO clauses are optional, you
must specify at least one of them.
Arguments
expKey is an expression that returns the key value to place in the index for each record in the current work area. expKey can be character, date, logical, or numeric type. The maximum length of the index key expression is determined by the driver.
TAG cOrderName is the name of the order to be created. cOrderName can be any CA-Clipper expression that evaluates to a string constant.
TOcOrderBagName is the name of a disk file containing one or more orders. The active RDD determines the order capacity of an order bag. The default DBFNTX driver only supports single-order bags, while other RDDs may support multiple-order bags (e.g., the DBFCDX and DBFMDX drivers). You may specify cOrderBagName as the file name with or without a path name or extension. If an extension is not provided as part of cOrderBagName, CA-Clipper will use the default extension of the current RDD.
Both the TAG and the TO clauses are optional, but you must use at least one of them.
FORlCondition specifies the conditional set of records on which to create the order. Only those records that meet the condition are included in the resulting order. lCondition is an expression that may be no longer than 250 characters under the DBFNTX and DBFNDX drivers. The maximum value for these expressions is determined by the RDD. The FOR condition is stored as part of the order bag and used when updating or recreating the index using the REINDEX command. Duplicate key values are not added to the order bag.
Drivers that do not support the FOR condition will produce an "unsupported" error.
The FOR clause provides the only scoping that is maintained for all database changes. All other scope conditions create orders that do not reflect database updates.
ALL specifies all orders in the current or specified work area. ALL is the default scope of INDEX .
WHILElCondition specifies another condition that must be met by each record as it is processed. As soon as a record is encountered that causes the condition to fail, the INDEX command terminates. If a WHILE clause is specified, the data is processed in the controlling order. The WHILE condition is transient (i.e., it is not stored in the file and not used for index updates and REINDEXing purposes). The WHILE clause creates temporary orders, but these orders are not updated.
Drivers that do not support the WHILE condition will produce an "unsupported" error.
Using the WHILE clause is more efficient and faster than using the FOR clause. The WHILE clause only processes data for which lCondition is true (.T.) from the current position. The FOR clause, however, processes all data in the data source.
NEXTnNumber specifies the portion of the database to process. If you specify NEXT, the database is processed in the controlling order for the nNumber number of identities. The scope is transient (i.e., it is not stored in the order and not used for REINDEXing purposes).
RECORDnRecord specifies the processing of the specified record.
REST specifies the processing of all records from the current position of the record pointer to the end of file (EOF).
EVALbBlock evaluates a code block every nInterval, where nInterval is a value specified by the EVERY clause. The default value is 1. This is useful in producing a status bar or odometer that monitors the indexing progress. The return value of bBlock must be a logical data type. If bBlock returns false (.F.), indexing halts.
EVERYnInterval is a clause containing a numeric expression that modifies the number of times bBlock is EVALuated. The EVERY option of the EVAL clause offers a performance enhancement by evaluating the condition for every nth record instead of evaluating every record ordered. The EVERY keyword is ignored if you specify no EVAL condition.
UNIQUE specifies that the key value of each record inserted into the order be unique. Duplicate key values are not added to the order.
ASCENDING specifies that the keyed pairs be sorted in increasing order of value. If neither ASCENDING nor DESCENDING is specified, ASCENDING is assumed. Although not stored as an explicit part of the file, ASCENDING is an implicit file attribute that is understood by the REINDEX command.
Drivers that do not support the ASCENDING condition will produce an "unsupported" error. The following keywords are new to CA-Clipper 5.3.
DESCENDING specifies that the keyed pairs be sorted in decreasing order of value. Using this keyword is the same as specifying the Descend() function within expKey, but without the performance penalty during order updates. If you create a DESCENDING index, you will not need to use the Descend() function during a SEEK. DESCENDING is an attribute of the file, where it is stored and used for REINDEXing purposes.
Drivers that do not support the DESCENDING condition will produce an "unsupported" error.
USECURRENT specifies that only records in the controlling order—and within the current range as specified by ORDSETSCOPE()—will be included in this order. This is useful when you have already created a conditional order and want to reorder the records which meet that condition, and/or to further restrict the records meeting a condition. If not specified, all records in the database file are included in the order.
ADDITIVE specifies that any open orders should remain open. If not specified, all open orders are closed before creating the new one. Note, however, that the production index file is never closed.
CUSTOM specifies that a custom built order will be created for RDDs that support them. A custom built order is initially empty, giving you complete control over order maintenance. The system does not automatically add and delete keys from a custom built order. Instead, you explicitly add and delete keys using ordKeyAdd() and ordKeyDel(). This capability is excellent for generating pick lists of specific records and other custom applications.
NOOPTIMIZE specifies that the FOR condition will not be optimized. If NOOPTIMIZE is not specified, the FOR condition will be optimized if the RDD supports optimization.
Description
The INDEX command adds a set of keyed pairs, ordered by expKey to a file specified by cOrderBagName using the database open in the current work area.
In RDDs that support production or structural indexes (e.g., DBFCDX, DBFMDX), if you specify a tag but do not specify an order bag, the tag is created and added to the order bag. If no production or structural index exists, it will be created and the tag will be added to it.
When using RDDs that support multiple order bags, you must explicitly SET ORDER (or ordSetFocus()) to the desired controlling order. If you do not specify a controlling order, the data file will be viewed in natural order.
If cOrderBagName does not exist, it is created in accordance with the RDD in the current or specified work area.
If cOrderBagName exists and the RDD specifies that order bags can only contain a single order, cOrderBagName is erased and the new order is added to the order bag and to the order list in the current or specified work area.
If cOrderBagName exists and the RDD specifies that order bags can contain multiple tags, cOrderName is created if it does not already exist; otherwise, cOrderName is replaced in cOrderBagName and the order is added to the order list in the current or specified work area.
ASCENDING or DESCENDING specifies the sequence of keyed pairs in the order. If neither clause is specified, the default is ASCENDING.
If you specify the UNIQUE clause, the resulting order will contain only unique records. Some RDDs may do this by only including record references to a key value once. Others may produce a runtime recoverable error as a non-unique key insertion is attempted.
The EVAL clause lets you specify a code block to be evaluated as each record is placed in the order. The EVERY clause lets you modify how often bBlock is called. Instead of evaluation as each record is placed in the order, evaluation only occurs as every nInterval records are placed in the order.
The INDEX command accepts certain clauses that let the user create conditional and partial orders. Some orders are intended to be maintained across the application, others are considered "temporary" orders.
The FOR clause provides the only order scoping that is permanent and can be maintained across the life of the application. The string passed as the FOR condition is stored within the order for later use in maintaining the order. Though only accessing part of a database, orders created using this clause exist as long as the database is active. The FOR clause lets you create maintainable scoped orders.
The WHILE, NEXT, REST and RECORD clauses process data from the current position of the database cursor in the default or specified work area. If you specify these clauses, the order list remains open and the active order is used to organize the database while it is being created. These clauses let you create temporary (non-maintainable) orders. Orders created using these clauses contain records in which lCondition is true (.T.) at the location of the record pointer.
Notes
RDD support: Not all RDDs support all aspects of the INDEX command. See the "Replaceable Database Driver Architecture" chapter in the Drivers Guide for details on a particular RDD.
Examples
■ The following example creates a simple order (index) based on
one field (Acct):
USE Customer NEW
INDEX ON Customer->Acct TO CuAcct
■ This example creates a conditional order (index) based on a
FOR clause. This index will contain only records whose field
TransDate contains a date greater than or equal to January 1, 1995:
USE Invoice NEW
INDEX ON Invoice->TransDate ;
TO InDate ;
FOR ( Invoice->TransDate >= CToD( "01/01/95" ) )
■ This example creates an order in a multiple-order bag (i.e., a
tag in
an index that can support multiple tags in an index file):
USE Customer NEW
INDEX ON Customer->Acct TAG CuAcct TO Customer
■ The following example creates an order that calls a routine,
MyMeter, during its creation:
#define MTR_INCREMENT 10
USE Customer NEW
INDEX ON Customer->Acct TO CuAcct EVAL ;
{|| MYMETER() } EVERY MTR_INCREMENT
FUNCTION MYMETER()
STATIC nRecsDone := 0
nRecsDone := += MTR_INCREMENT
? ( nRecsDone/LastRec() ) * 100
RETURN (.T.)
INIT PROCEDURE declares a procedure that will be executed at program startup.
idProcedure is the name of the initialization procedure to declare. Initialization procedure names can be any length, but only the first 10 characters are significant. Names may not begin with an underscore but can contain any combination of characters, numbers, or underscores.
idParam list is the declaration of one or more parameter variables. Variables specified in this list are declared local.
FIELD declares a list of identifiers to use as field names whenever encountered. If the IN clause is specified, referring to the declared name includes an implicit reference to the specified alias.
LOCAL declares and, optionally, initializes a list of variables or arrays whose visibility and lifetime is the current procedure.
MEMVAR declares a list of identifiers to use as private or public memory variables or arrays whenever encountered.
RETURN passes control to the next initialization procedure or the first executable routine in the program, if no other initialization procedures are pending.
Description
The INIT PROCEDURE statement declares a procedure that will be executed at program startup. INIT procedures are called prior to the first executable statement in a CA-Clipper application, and are useful for performing common initialization tasks such as reading configuration settings, or opening a communications port.
INIT PROCEDUREs are executed implicitly by CA-Clipper at program startup. The visibility of initialization procedures is restricted to the system; therefore, it is not possible to call an INIT PROCEDURE from a procedure or user-defined function. Each INIT PROCEDURE receives a copy of the DOS command line arguments used to invoke the application.
Control passes from one INIT PROCEDURE to the next until all procedures in the initialization list have been called. Control then passes to the first executable statement in the program.
The ANNOUNCE statement declares a module identifier for a source (.prg) file. Once declared, INIT PROCEDUREs are referenced by this module identifier. An application may use any number of initialization procedures by explicitly REQUESTing their module identifiers.
The INIT PROCEDUREs requested for an application are collectively referred to as the initialization list. There is no default execution order of procedures in the initialization list; however, the following rules apply:
■ The CA-Clipper initialization procedure, CLIPINIT, is always
called first
■ If an INIT PROCEDURE is declared in the same source (.prg)
file as the application's primary (root) routine, it will be the last initialization procedure called
CLIPINIT is called first to establish system integrity by installing the default error recovery system (ErrorSys). Once CLIPINIT has finished executing, control passes to the next INIT PROCEDURE in the initialization list.
If an error is raised during system initialization, the system returns to DOS, and pending initialization procedures are not called.
Examples
■ The following example uses both INIT and EXIT PROCEDUREs to
save and restore the context of the operating system. You can have
your program, "Myfile.prg", REQUEST SaveDos:
ANNOUNCE SaveDos
#define DOS_SCREEN 1
#define DOS_ROW 2
#define DOS_COL 3
#define DOS_CURSOR 4
#define DOS_COUNT 4
STATIC saSaveDos[ SD_COUNT ]
INIT PROCEDURE dosSave()
SAVE SCREEN TO saSaveDos[ DOS_SCREEN ]
saSaveDos[ DOS_ROW ] := Row()
saSaveDos[ DOS_COL ] := Col()
saSaveDos[ DOS_CURSOR ] := SetCursor()
RETURN
EXIT PROCEDURE dosRestore()
RESTORE SCREEN FROM saSaveDos[ DOS_SCREEN ]
SETPOS ( saSaveDos[ DOS_ROW ], saSaveDos[ DOS_COL ] )
SetCursor( saSaveDos[ DOS_CURSOR ] )
RETURN
expPrompt is an optional prompt displayed before the input area. The prompt can be an expression of any data type.
TOidVar specifies the name of the variable to be assigned the evaluation result. If idVar is not visible or does not exist, a private variable is created and assigned the result.
Description
INPUT is a console command and wait state that takes entry from the keyboard in the form of a valid expression of up to 255 characters and any data type. When invoked, INPUT sends a carriage return/linefeed to the screen, displays the prompt, and begins accepting keyboard input at the first character position following the prompt. Input greater than MaxCol() wraps to the next line.
Pressing Return terminates entry of the expression. The expression is then compiled and evaluated using the macro operator (&), and the result assigned to idVar. If the variable is not visible or does not exist, it is created as a private. If no expression is entered, no action is taken.
INPUT supports only two special keys: Backspace and Return. Esc is not supported. Backspace deletes the last character typed. Return confirms entry and is the only key that can terminate an INPUT.
Examples
■ In this example INPUT assigns a keyboard entry to an existing
local variable:
LOCAL exp
INPUT "Expression: " TO exp
IF exp != NIL
? exp
ELSE
? "No expression entered"
ENDIF
nExp is a numeric expression to be converted to an integer.
Returns
Int() returns an integer numeric value.
Description
Int() is a numeric function that converts a numeric value to an integer by truncating—not rounding—all digits to the right of the decimal point. Int() is useful in operations where the decimal portion of a number is not needed.
Examples
■ These examples demonstrate the results of various invocations
of the INT() function:
? INT(100.00) // Result: 100
? INT(.5) // Result: 0
? INT(-100.75) // Result: -100
Determine if the leftmost character in a string is alphabetic
Syntax
IsAlpha(<cString>) → lBoolean
Arguments
cString is the character string to be examined.
Returns
IsAlpha() returns true (.T.) if the first character in cString is alphabetic; otherwise, it returns false (.F.).
Description
IsAlpha() is a character function that determines if the specified string begins with an alphabetic character. An alphabetic character consists of any uppercase or lowercase letter from A to Z. IsAlpha() returns false (.F.) if the string begins with a digit or any other character.
Examples
■ These examples demonstrate various results of IsAlpha():
? IsAlpha("AbcDe") // Result: .T.
? IsAlpha("aBcDE") // Result: .T.
? IsAlpha("1BCde") // Result: .F.
? IsAlpha(".FRED") // Result: .F.
Determine if the current computer has color capability
Syntax
IsColor() | ISCOLOUR() → lBoolean
Returns
IsColor() returns true (.T.) if there is a color graphics card installed; otherwise, it returns false (.F.).
Description
IsColor() is a screen function that allows you to make decisions about the type of screen attributes to assign (color or monochrome). Note that some monochrome adapters with graphics capability return true (.T.).
Examples
■ This example installs color attribute variables at runtime:
IF IsColor()
cBox = "BG+/B, W/N"
cSays = "BG/B, W/N"
cGets = "W/N, N/W"
ELSE
cBox = "W+"
cSays = "W/N, N+/W"
cGets = "W/N, N/W"
ENDIF
.
. <statements>
.
SetColor(cSays)
Determine if the leftmost character in a character string is a digit
Syntax
IsDigit(<cString>) → lBoolean
Arguments
cString is the character string to be examined.
Returns
IsDigit() returns true (.T.) if the first character of the character string is a digit between zero and nine; otherwise, it returns false (.F.).
Description
IsDigit() is a character function that determines whether the first character in a string is a numeric digit between zero and nine. If any other character is the first character of the cString, IsDigit() returns false (.F.).
IsDigit() is useful where you need to know if the current character string is a number before converting it to a numeric value with the Val() function.
Examples
■ These examples demonstrate various results of IsDigit():
? IsDigit("AbcDe") // Result: .F.
? IsDigit("1abcd") // Result: .T.
? IsDigit(".12345") // Result: .F.
Determine if the leftmost character is a lowercase letter
Syntax
IsLower(<cString>) → lBoolean
Arguments
cString is the character string to be examined.
Returns
IsLower() returns true (.T.) if the first character of the character string is a lowercase letter; otherwise, it returns false (.F.).
Description
IsLower() is a character function that determines whether the first character of a character string is lowercase. It is the inverse of IsUpper() which determines whether a character begins with an uppercase character.
Both IsLower() and IsUpper() relate to the Lower() and Upper() functions which actually convert lowercase characters to uppercase, and vice versa.
Examples
■ These examples demonstrate various results of IsLower():
? IsLower("aBcDe") // Result: .T.
? IsLower("AbcDe") // Result: .F.
? IsLower("1abcd") // Result: .F.
? IsLower("abcd") // Result: .T.
IsPrinter() returns true (.T.) if LPT1 is ready; otherwise, it returns false (.F.).
Description
IsPrinter() is a printer function that determines whether the parallel port (LPT1) is online and ready to print. IsPrinter() is hardware-dependent and, therefore, only works on IBM BIOS compatible systems.
You can check IsPrinter() to make sure the printer is ready before you begin a print operation; however, if an error occurs during the print operation, a runtime error is generated.
Examples
■ This example tests the parallel port for readiness with up to
25 retries. If the parallel port is ready, the printer operation
begins:
LOCAL nCount := 0, nTimes := 25, lReady
//
DO WHILE nCount++ <= nTimes .AND. !(lReady := ;
IsPrinter())
ENDDO
//
IF lReady
REPORT FORM Sales TO PRINTER
ELSE
? "Printer not ready..."
BREAK
ENDIF
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/EXAMPLEA.ASM.
Determine if the leftmost character in a string is uppercase
Syntax
IsUpper(<cString>) → lBoolean
Arguments
cString is the character string to be examined.
Returns
IsUpper() returns true (.T.) if the first character is an uppercase letter; otherwise, it returns false (.F.).
Description
IsUpper() is a character function that determines whether the first character of a string is uppercase. It is the inverse of IsLower(). Both IsUpper() and IsLower() relate to the Upper() and Lower() functions which actually convert uppercase characters to lowercase, and vice versa.
Examples
■ These examples illustrate IsUpper() applied to various values:
? IsUpper("AbCdE") // Result: .T.
? IsUpper("aBCdE") // Result: .F.
? IsUpper("$abcd") // Result: .F.
? IsUpper("8ABCD") // Result: .F.
Create a new database file by merging records/fields from two work areas
Syntax
JOIN WITH <xcAlias> TO <xcDatabase>
FOR <lCondition> [FIELDS <idField list>]
Arguments
WITHxcAlias is the name of the work area to merge with records from the current work area. You can specify it either as a literal alias or as a character expression enclosed in parentheses.
TOxcDatabase is the name of the target database file specified either as a literal filename or as a character expression enclosed in parentheses.
FORlCondition selects only records meeting the specified condition.
FIELDSidField list is the projection of fields from both work areas into the new database file. To specify any fields in the secondary work area, reference them with the alias. If the FIELDS clause is not specified, all fields from the primary work area are included in the target database file.
Description
JOIN creates a new database file by merging selected records and fields from two work areas based on a general condition. JOIN works by making a complete pass through the secondary work area for each record in the primary work area, evaluating the condition for each record in the secondary work area. When the lCondition is true (.T.), a new record is created in the target database file using the FIELDS specified from both work areas.
If SET DELETED is OFF, deleted records in both source files (i.e., the two files being JOINed) are processed. However, their deleted status is not retained in the target xcDatabase. No record in the target file is marked for deletion regardless of its deleted status in either of the source files.
If SET DELETED is ON, no deleted records are processed in either of the source files. Thus, deleted records do not become part of the target xcDatabase. Similarly, filtered records are not processed and do not become part of the target file.
Warning! The number of records processed will be the LastRec() of the primary work area multiplied by the LastRec() of the secondary work area. For example, if you have two database files with 100 records each, the number of records JOIN processes is the equivalent of sequentially processing a single database file of 10,000 records. Therefore, use this command carefully.
Examples
■ This example joins Customer.dbf to Invoices.dbf to produce
Purchases.dbf:
USE Invoices NEW
USE Customers NEW
JOIN WITH Invoices TO Purchases;
FOR Last = Invoices->Last;
FIELDS First, Last, Invoices->Number, ;
Invoices->Amount
cString is the string to stuff into the keyboard buffer.
Description
KEYBOARD is a keyboard command that stuffs cString into the keyboard buffer after clearing any pending keystrokes. The characters remain in the keyboard buffer until fetched by a wait state such as ACCEPT, INPUT, READ, AChoice(), MemoEdit(), and dbEdit(), or Inkey(). In addition to display characters, cString may include control characters.
Generally, to convert an Inkey() code of a control key to a character value, use Chr(). There are, however, some limitations. You can only stuff characters with Inkey() codes between zero and 255, inclusive, into the keyboard buffer.
Typically, KEYBOARD is used in a SET KEY procedure to reassign keys in a wait state. Another use within the AChoice() user function is to input the keys you want AChoice() to execute before returning control to it. The same concept applies to dbEdit().
Examples
■ This example uses KEYBOARD to stuff a GET with an item
selected from a picklist each time the GET is entered:
#include "Inkey.ch"
LOCAL cVar1 := Space(10), nVar := 2500, ;
cVar2 := Space(10)
CLEAR
@ 09, 10 GET cVar1
@ 10, 10 GET cVar2 WHEN PickList()
@ 11, 10 GET nVar
READ
RETURN
FUNCTION PickList
STATIC aList := { "First", "Second", ;
"Three", "Four" }
LOCAL cScreen, nChoice, nKey := LastKey()
cScreen := SaveScreen(10, 10, 14, 20)
@ 10, 10 TO 14, 20 DOUBLE
IF (nChoice := AChoice(11, 11, 13, 19, aList)) != 0
KEYBOARD CHR(K_CTL_Y) + aList[nChoice] + ;
Chr(nKey)
ENDIF
RestScreen(10, 10, 14, 20, cScreen)
RETURN .T.
Convert a CA-Clipper numeric value to a 32-bit binary integer
Syntax
L2Bin(<nExp>) → cBinaryInteger
Arguments
nExp is the numeric value to be converted. Decimal digits are truncated.
Returns
L2Bin() returns a four-byte character string formatted as a 32-bit binary integer.
Description
L2Bin() is a low-level file function used with FWrite() to write CA-Clipper numeric values to a binary file. This function is like I2Bin() which formats a CA-Clipper numeric to a 16-bit binary value.
■ This example creates a new binary file, and then writes a
series of numbers to the files using L2Bin() to convert the numeric
value to 32-bit binary form:
#include "Fileio.ch"
//
LOCAL nNumber, nHandle
nHandle := FCreate("MyFile", FC_NORMAL)
FOR nNumber := 1 TO 100
FWrite(nHandle, L2Bin(nNumber) + Chr(0))
NEXT
FClose(nHandle)
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/EXAMPLEA.ASM.
Return the Inkey() value of the last key extracted from the keyboard buffer
Syntax
LastKey() → nInkeyCode
Returns
LastKey() returns an integer value from -39 to 386 for keyboard events and integer values from 1001 to 1007 for mouse events. This value identifies either the key extracted from the keyboard buffer or the mouse event that last occurred. If the keyboard buffer is empty, and no mouse events are taking place, LastKey() returns 0. LastKey() returns values for all ASCII characters, function, Alt+Function, Alt+Letter, and Ctrl+Letter key combinations.
Description
LastKey() is a function that reports the Inkey() value of the last key fetched from the keyboard buffer by the Inkey() function, or the next mouse event, or a wait state such as ACCEPT, INPUT, READ, WAIT, AChoice(), dbEdit(), or MemoEdit(). The time LastKey() waits is based on the operating system clock and is not related to the microprocessor speed. LastKey() retains its current value until another key is fetched from the keyboard buffer.
LastKey() has a number of uses which include:
■ Determining the key that terminates a READ
■ Determining the key that exits the current Get object within a
user-defined function, invoked by a VALID clause
■ Identifying an exception key in the user function of
LastKey() is also used with Updated() to determine if any Get object's buffer was changed during a READ.
LastKey() is related to NextKey() and ReadKey(). NextKey() reads the current key pending in the keyboard buffer without removing it. Use NextKey() instead of Inkey() when polling for a key.
For a complete list of Inkey() codes and inkey.ch constants for each key, refer to the Error Messages and Appendices Guide.
Examples
■ This example illustrates a typical application of LastKey() to
test the key that exits a READ. If the user exits with any key other
than Esc and a GET was changed, the specified database file is
updated:
#include "Inkey.ch"
//
USE Customer NEW
MEMVAR->balance = Customer->Balance
@ 10, 10 SAY "Current Balance" GET MEMVAR->balance
READ
//
IF (LastKey() != K_ESC) .AND. Updated()
REPLACE Customer->Balance WITH MEMVAR->balance
ENDIF
Determine the number of records in the current .dbf file
Syntax
LastRec() | RecCount()* → nRecords
Returns
LastRec() returns the number of physical records in the current database file as an integer numeric value. Filtering commands such as SET FILTER or SET DELETED have no effect on the return value. LastRec() returns zero if there is no database file in USE in the current work area.
Description
LastRec() is a database function that determines the number of physical records in the current database file. LastRec() is identical to RecCount() which is supplied as a compatibility function.
By default, LastRec() operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression (see example below).
Note: Although the functionality of RecNo() has been expanded to encompass the concept of "identity," the LastRec() function continues to return only record numbers—not identities. LastRec() has no expanded functionality, so it is not "identity-aware."
Examples
■ This example illustrates the relationship between LastRec(),
RecCount(), and COUNT:
USE Sales NEW
? LastRec(), RecCount() // Result: 84 84
//
SET FILTER TO Salesman = "1001"
COUNT TO nRecords
? nRecords, LastRec() // Result: 14 84
■ This example uses an aliased expression to access the number
of records in a open database file in an unselected work area:
USE Sales NEW
USE Customer NEW
? LastRec(), Sales->(LastRec())
xcLabel is the name of the label (.lbl) file that contains the FORM definition of the LABEL and can be specified either as a literal file name or as a character expression enclosed in parentheses. If an extension is not specified .lbl is assumed.
TO PRINTER echoes output to the printer.
TO FILExcFile echoes output to xcFile. Specify xcFile as a literal file name or as a character expression enclosed in parentheses. If an extension is not specified, .txt is added.
NOCONSOLE suppresses all LABEL FORM output to the console. If not specified, output automatically displays to the console unless SET CONSOLE is OFF.
scope is the portion of the current database file to display labels. The default is ALL records.
WHILElCondition specifies the set of records meeting the condition from the current record until the condition fails.
FORlCondition specifies to LABEL FORM, the conditional set of records within the given scope.
SAMPLE displays test labels as rows of asterisks. Each test label has the same number of columns and rows as the label definition. Then, following each test label display, is the query, "Do you want more samples?" Answering "Y" forces another test label display. Answering "N" causes LABEL FORM to display the actual labels for the specified scope and condition.
Description
LABEL FORM is a console command that sequentially accesses records in the current work area, displaying labels using a definition stored in a .lbl file. Create the .lbl using RL.EXE or by dBASE III PLUS. Refer to the "Report and Label Utility" chapter in the Programming and Utilities Guide for more information about creating label definitions.
When invoked, output is sent to the screen and, optionally, to the printer and/or a file. To suppress output to the screen while printing or echoing output to a file, SET CONSOLE OFF before invocation of LABEL FORM or use the NOCONSOLE keyword.
When invoked, LABEL FORM searches the current SET PATH drive and directory, if the xcLabel file is not found in the current directory and the path is not specified.
Notes
■ Interrupting LABEL FORM: To interrupt a LABEL FORM, use
Inkey() as a part of the FOR condition to test for an interrupt key press. See the example below.
■ Printer margin: LABEL FORM obeys the current SET MARGIN for
output echoed to the printer.
Examples
■ This example prints a set of labels and writes them to a file
with a single command. Two forms of the command are shown:
LOCAL cLabel := "Sales", cFile := "Sales"
USE Sales INDEX Sales NEW
LABEL FORM Sales TO PRINTER TO FILE Sales
LABEL FORM (cLabel) TO PRINTER TO FILE (cFile)
■ This example interrupts LABEL FORM using Inkey() to test if
the user pressed the Esc key:
#define K_ESC 27
USE Sales INDEX Sales NEW
LABEL FORM Sales WHILE Inkey() != K_ESC
Extract a substring beginning with the first character in a string
Syntax
Left(<cString>, <nCount>) → cSubString
Arguments
cString is a character string from which to extract characters. The maximum size of cString is 65,535 (64K) bytes.
nCount is the number of characters to extract.
Returns
Left() returns the leftmost nCount characters of cString as a character string. If nCount is negative or zero, Left() returns a null string (""). If nCount is larger than the length of the character string, Left() returns the entire string.
Description
Left() is a character function that returns a substring of a specified character string. It is the same as SubStr(cString, 1, nCount). Left() is also like Right(), which returns a substring beginning with the last character in a string.
Left(), Right(), and SubStr() are often used with both the At() and RAt() functions to locate the first and/or the last position of a substring before extracting it.
Examples
■ This example extracts the first three characters from the left
of the target string:
? Left("ABCDEF", 3) // Result: ABC
■ This example extracts a substring from the beginning of a
string up to the first occurrence of a comma:
LOCAL cName := "James, William"
? Left(cName, At(",", cName) - 1) // Result: James
Return the length of a character string or the number of elements in an array
Syntax
Len(<cString> | <aTarget>) → nCount
Arguments
cString is the character string to count.
aTarget is the array to count.
Returns
Len() returns the length of a character string or the number of elements in an array as an integer numeric value. If the character string is a null string ("") or the array is empty, Len() returns zero.
Description
Len() is a character and array function that returns the length of a character string or the number of elements in an array. With a character string, each byte counts as one, including an embedded null byte (Chr(0)). By contrast, a null string ("") counts as zero.
For an array, Len() returns the number of elements. If the array is multidimensional, subarrays count as one element. This means that the Len() of a nested or multidimensional array simply returns the length of the first dimension. To determine the number of elements in other dimensions, use Len() on the subarrays as shown in the example below. Note that nested arrays in CA-Clipper need not have uniform dimensions.
Examples
■ These examples demonstrate Len() with various arguments:
? Len("string of characters") // Result: 20
? Len("") // Result: 0
? Len(Chr(0)) // Result: 1
//
LOCAL aTest[10]
? Len(aTest) // Result: 10
■ This example creates a literal two-dimensional array, and then
returns the number of elements in the subarray contained in the first
element of the original array:
LOCAL aArray := { {1, 2}, {1, 2}, {1, 2} }
? Len(aArray) // Result: 3
? Len(aArray[1]) // Result: 2
■ This example navigates a multidimensional array using Len():
LOCAL aArray := { {1, 2}, {1, 2}, {1, 2} }
LOCAL nRow, nColumn, nRowCount, nColumnCount
//
nRowCount = Len(aArray)
FOR nRow = 1 TO nRowCount
nColumnCount = Len(aArray[nRow])
FOR nColumn = 1 TO nColumnCount
? nRow, nColumn, aArray[nRow][nColumn]
NEXT
NEXT
■ In this example a function returns an array of numeric values
that describe the dimensions of a nested or multidimensional array.
The function assumes that the array has uniform dimensions:
FUNCTION Dimensions( aArray )
LOCAL aDims := {}
DO WHILE ( ValType(aArray) == "A" )
AAdd( aDims, Len(aArray) )
aArray := aArray[1]
ENDDO
RETURN (aDims)
A list box displays a list of strings (or items) to the user. You can use the methods of ListBox to add, arrange, remove, and interrogate the items in a list box.
Methods link
Class Function
ListBox() Create a new ListBox object
ListBox(nTop, nLeft, nBottom, nRight
[, lDropDown]) → oListBox
Arguments
nTop is a numeric value that indicates the top screen row of the list box.
nLeft is a numeric value that indicates the left screen column of the list box.
nBottom is a numeric value that indicates the bottom screen row of the list box.
nRight is a numeric value that indicates the right screen column of the list box.
lDropDown is an optional logical value that indicates whether the list box is a drop-down list box. A value of true (.T.) indicates that it is a drop-down list box; otherwise, a value of false (.F.) indicates that it is not. The default is false (.F.).
Returns
Returns a ListBox object when all of the required arguments are present; otherwise, ListBox() returns NIL.
Exported Instance Variables
bitmap The bitmap file to display on the button
bitmap (Assignable)
Contains a character string that indicates a bitmap file to be displayed on the button. Drive and directory names are not allowed; the file name extension is required. A bitmap file can be stored as a file on disk or in a bitmap library. If stored as a file, the file must reside in the same directory as the application. If stored in a bitmap library, the library must reside in the same directory as the application and it also must have the same name as the application with a .bml extension.
CA-Clipper will search for the file name first and, if it is not found, search in the bitmap library second. If no file is found either on disk or in the library, no bitmap will be displayed. This instance variable only affects applications running in graphic mode and is ignored in text mode.
bottom Numeric value indicating bottommost screen row
bottom (Assignable)
Contains a numeric value that indicates the bottommost screen row where the list box is displayed.
buffer Numeric value indicating position of item
buffer
Contains a numeric value that indicates the position in the list of the selected item.
capCol Numeric value indicating location of caption by column
capCol (Assignable)
Contains a numeric value that indicates the screen column where the list box's caption is displayed.
capRow Numeric value indicating location of caption by row
capRow (Assignable)
Contains a numeric value that indicates the screen row where the list box's caption is displayed.
caption Character string describing list box
caption (Assignable)
Contains a character string that concisely describes the list box on the screen.
When present, the & character specifies that the character immediately following it in the caption is the list box's accelerator key. The accelerator key provides a quick and convenient mechanism for the user to move input focus from one data input control to a list box. The user performs the selection by pressing the Alt key in combination with an accelerator key. The case of an accelerator key is ignored.
cargo User-definable variable
cargo (Assignable)
Contains a value of any type that is ignored by the ListBox object. ListBox:cargo is provided as a user-definable slot allowing arbitrary information to be attached to a ListBox object and retrieved later.
coldBox Optional string specifying characters
coldBox (Assignable)
Contains an optional string that specifies the characters to use when drawing a box around the list box when it does not have input focus. Its default value is a single line box.
Standard Box Types
Constant Description
B_SINGLE Single line box
B_DOUBLE Double line box
B_SINGLE_DOUBLE Single line top/bottom, double line sides
B_DOUBLE_SINGLE Double line top/bottom, single line sides
Box.ch contains manifest constants for the ListBox:coldBox value.
colorSpec Character string indicating color
colorSpec (Assignable)
Contains a character string that indicates the color attributes that are used by the list box's display() method. If the list box is a drop-down list, the string must contain eight color specifiers, otherwise it must contain seven color specifiers.
Note: The background colors of the ListBox Color Attributes are ignored in graphic mode.
ListBox Color Attributes
Position Applies To Default Value from
in colorSpec System Color Setting
1 List box items that are not selected Unselected
when the list does not have input focus
2 The selected list box item when the Unselected
list does not have input focus
3 List box items that are not selected Unselected
when the list has input focus
4 The selected list box item when the Enhanced
list has input focus
5 The list box's border Border
6 The list box's caption Standard
7 The list box caption's accelerator key Background
8 The list box's drop-down button Standard
Note: The colors available to a DOS application are more limited than those for a Windows application. The only colors available to you here are listed in the drop-down list box in the item properties.
dropDown Optional logical value indicating a drop-down list
dropDown
Contains an optional logical value that indicate whether the object is a drop-down list. A value of true (.T.) indicates that it is a drop-down list; otherwise, a value of false (.F.) indicates that it is not. The default is false.
fBlock Code block evaluated at each input focus change
fBlock (Assignable)
Contains an optional code block that, when present, is evaluated each time the ListBox object receives or loses input focus. The code block takes no implicit arguments. Use the ListBox:hasFocus variable to determine if the list box is receiving or losing input focus. A value of true (.T.) indicates that it is receiving input focus; otherwise, a value of false (.F) indicates that it is losing input focus.
This code block is included in the ListBox class to provide a method of indicating when an input focus change event has occurred. The name "fBlock" refers to focus block.
hasFocus Logical value indicating the input focus
hasFocus
Contains a logical value that indicates whether the ListBox object has input focus. ListBox:hasFocus contains true (.T.) if it has input focus; otherwise, it contains false (.F.).
hotBox Optional string specifying characters
hotBox (Assignable)
Contains an optional string that specifies the characters to use when drawing a box around the list box when it has input focus. Its default value is a double-line box.
Standard Box Types
Constant Description
B_SINGLE Single line box
B_DOUBLE Double line box
B_SINGLE_DOUBLE Single line top/bottom, double line sides
B_DOUBLE_SINGLE Double line top/bottom, single line sides
Box.ch contains manifest constants for the ListBox:hotBox value.
isOpen Logical value indicating visibility of list
isOpen
Contains a logical value that indicates whether the list is visible. A value of true (.T.) indicates that the list is visible; otherwise a value of false (.F.) indicates that it is not visible. When ListBox:dropDown is false (.F.), ListBox:isOpen is always true (.T.); otherwise, ListBox:isOpen is true (.T.) during the period of time between calling ListBox:open() and ListBox:close().
itemCount Numeric value total number of items
itemCount
Contains a numeric value that indicates the total number of items contained within the ListBox object.
left Numeric value indicating leftmost screen column
left (Assignable)
Contains a numeric value that indicates the leftmost screen column where the list box is displayed.
message Character string describing the list box
message (Assignable)
Contains a character string that describes the list box. It is displayed on the screen's status bar line.
right Numeric value indicating rightmost screen column
right (Assignable)
Contains a numeric value that indicates the rightmost screen column where the list box is displayed.
sBlock Code block evaluated at every state change
sBlock (Assignable)
Contains an optional code block that, when present, is evaluated immediately after the ListBox object's selection changes. The code block takes no implicit arguments. Use the ListBox:buffer variable to determine the current selection.
This code block is included in the ListBox class to provide a method of indicating when a state change event has occurred. The name "sBlock" refers to state block.
top Numeric value indicating topmost screen row
top (Assignable)
Contains a numeric value that indicates the topmost screen row where the list box is displayed.
topItem Numeric value indicating position of first item
topItem (Assignable)
Contains a numeric value that indicates the position in the list box of the first visible item.
typeOut Logical value indicating list contents
typeOut
Contains a logical value that indicates whether the list contains any items. A value of true (.T.) indicates that the list contains selectable items; otherwise, a value of false (.F.) indicates that the list is empty.
vScroll Optional ScrollBar object whose orientation must be vertical
vScroll (Assignable)
Contains an optional ScrollBar object whose orientation must be vertical. The scroll bar thumb position reflects the relationship between the current first visible item on the screen and the total number of possible top items (total number of items - number of visible items - 1).
When present, the scroll bar is automatically integrated within the behaviors of the following ListBox object methods: addItem(), display(), delItem(), HitTest(), insItem(), nextItem(), prevItem(), and Select().
Exported Methods
addItem() Appends a new item to a list
oListBox:addItem(cText [, expValue]) → self
cText is a character string that indicates the item's text to display in the list.
expValue is a value that is associated with the list item. If omitted, the item's associated data will be NIL.
addItem() is a method of the ListBox class that is used for appending a new item to a list. When adding an item, an optional value may be included. This enables you to associate pertinent data with the text displayed in the list.
Note: When present, the scroll bar is automatically updated to reflect the addition of the new item.
close() Restores screen under drop-down list box
oListBox:close() → self
close() is a method of the ListBox class that is used for restoring the screen under a drop-down list box.
delItem() Removes item from a list
oListBox:delItem(nPosition) → self
nPositionis a numeric value that indicates the position in the list of the item to delete.
delItem() is a method of the ListBox class that is used for removing an item from a list. ListBox:buffer is automatically adjusted when an item is deleted while the last item in the list is selected.
Note: When present, the scroll bar is automatically updated to reflect the deletion of the item.
display() Shows a list box and its caption
oListBox:display() → self
display() is a method of the ListBox class that is used for showing a list and its caption on the screen. display() uses the values of the following instance variables to correctly show the list in its current context, in addition to providing maximum flexibility in the manner a list box appears on the screen: bottom, capCol, capRow, caption, coldBox, colorSpec, hasFocus, hotBox, itemCount, left, right, style, top, topItem, and vScroll.
Note: When present, the scroll bar is automatically displayed when the ListBox:display() method is called.
findText() Determines the position of an item within a list
oListBox:findText(cText [,nPosition]
[,lCaseSensitive] [,lExact]) → nPosition
cText is a character string that indicates the text that is being searched for.
nPosition is an optional numeric value that indicates the starting position in the list of the search. The default is 1.
lCaseSensitive is an optional logical value that indicates whether the search should be case sensitive. Set lCaseSensitive to true (.T.) to indicate that the search should be case sensitive; otherwise, set lCaseSensitive to false (.F.). The default is true (.T.).
lExact is an optional logical value that indicates whether the search enforces an exact comparison including length and trailing characters. A value of true (.T.) indicates that findText() searches for an exact match; otherwise, a value of false (.F.) indicates that it should not. The default is the current setExact() setting.
Returns a numeric value that indicates the position in the list of the first item from nPosition whose text matches cText, or 0 if ListBox:findText() is unsuccessful.
findText() is a method of the ListBox class that is used for determining whether an item is a member of a list and its position within the list. findText() always searches from nPosition to the end of the list and, when necessary, continues from the beginning of the list to nPosition - 1.
getData() Retrieves the data portion of a list box item
oListBox:getData(nPosition) → expValue
nPosition is a numeric value that indicates the position within the list of the item whose data is being retrieved.
Returns the data associated with the item in the list specified by nPosition.
getData() is a method of the ListBox class that is used for retrieving the data portion of a list box item.
getItem() Retrieves a list box item
oListBox:getItem(nPosition) → aItem
nPosition is a numeric value that indicates the position in the list of the item that is being retrieved.
Returns the list box item specified by nPosition expressed as a two-element array consisting of the item's text and data respectively. The text is a character string that indicates the item's text to display in the list. The data is a value that is associated with the list item.
getItem() is a method of the ListBox class that is used for retrieving a list box item.
getText() Retrieves the text portion of a list box item
oListBox:getText(nPosition) → cText
nPosition is a numeric value that indicates the position within the list of the item whose text is being retrieved.
Returns the text associated with the item in the list specified by nPosition.
getText() is a method of the ListBox class that is used for retrieving the text portion of a list box item.
HitTest() Indicates position of mouse cursor relative to list box
oListBox:hitTest(nMouseRow, nMouseCol)
→ nhitStatus
nMouseRow is a numeric value that indicates the current screen row position of the mouse cursor.
nMouseCol is a numeric value that indicates the current screen column position of the mouse cursor.
Returns a numeric value that indicates the relationship of the mouse cursor with the list box.
Applicable Hit Test Return Values
Value Constant Description
> 0 Not Applicable The position in the list of the item whose
region the mouse is within
0 HTNOWHERE The mouse cursor is not within the region of
the screen that the list box occupies
-1 HTTOPLEFT The mouse cursor is on the top left corner of
the list box's border
-2 HTTOP The mouse cursor is on the list box's top
border
-3 HTTOPRIGHT The mouse cursor is on the top right corner of
the list box's border
-4 HTRIGHT The mouse cursor is on the list box's right
border
-5 HTBOTTOMRIGHT The mouse cursor is on the bottom right corner
of the list box's border
-6 HTBOTTOM The mouse cursor is on the list box's bottom
border
-7 HTBOTTOMLEFT The mouse cursor is on the bottom left corner
of the list box's border
-8 HTLEFT The mouse cursor is on the list box's left
border
-1025 HTCAPTION The mouse cursor is on the list box's caption
-4097 HTDROPBUTTON The mouse cursor is on the list box's drop
down button
Button.ch contains manifest constants for the ListBox:hitTest() return value.
HitTest() is a method of the ListBox class that is used for determining if the mouse cursor is within the region of the screen that the list box occupies.
Note: When a scroll bar is present, its HitTest() method is automatically called to determine if the mouse cursor is within its region. If ScrollBar:hitTest() succeeds in determining that a "hit" has been achieved, ListBox:hitTest() returns the appropriate scroll bar hit test return code.
insItem() Inserts a new item to a list
oListBox:insItem(nPosition, cText,
[expValue]) → self
nPosition is a numeric value that indicates the position at which the new item is inserted.
cText is the item's text to display in the list.
expValue is a value that is associated with the list item. If omitted, the item's associated data will be NIL.
insItem() is a method of the ListBox class that is used for inserting a new item to a list. When inserting an item, an optional value may be included. This enables you to associate pertinent data with the text displayed in the list.
Note: When present, the scroll bar is automatically updated to reflect the insertion of the new item.
killFocus() Takes input focus away from the ListBox object
oListBox:killFocus() → self
killFocus() is a method of the ListBox class that is used for taking input focus away from a ListBox object. Upon receiving this message, the ListBox object redisplays itself and, if present, evaluates the code block within its fBlock variable.
This message is meaningful only when the ListBox object has input focus.
nextItem() Changes selected item to next one
oListBox:nextItem() → self
nextItem() is a method of the ListBox class that is used for changing the selected item from the current item to the one immediately following it. If necessary, nextItem() will call its display() method to ensure that the newly selected item is visible.
This message is meaningful only when the ListBox object has input focus.
Note: When present, the scroll bar is automatically updated to reflect the new first visible item in the list when the call to ListBox:nextItem() causes the list to be scrolled.
open() Saves screen under drop-down list box
oListBox:open() → self
open() is a method of the ListBox class that is used for saving the screen under a drop-down list box and displaying the list.
prevItem() Changes selected item to previous one
oListBox:prevItem() → self
prevItem() is a method of the ListBox class that is used for changing the selected item from the current item to the one immediately before it. If necessary, prevItem() will call its display() method to ensure that the newly selected item is visible.
This message is meaningful only when the ListBox object has input focus.
Note: When present, the scroll bar is automatically updated to reflect the new first visible item in the list when the call to ListBox:prevItem() causes the list to be scrolled.
nMethod indicates the manner in which the scroll operation is carried out. A call to ListBox:scroll() is typically issued in response to ScrollBar:hitTest returning that a hit has been established.
ListBox:Scroll Argument Values
Value Constant Result
-3074 HTSCROLLUNITDEC Scroll down one line
-3075 HTSCROLLUNITINC Scroll up one line
-3076 HTSCROLLBLOCKDEC Scroll down one window
-3077 HTSCROLLBLOCKINC Scroll up one window
Scroll() is a method of the ListBox class that is used for scrolling the contents of a list box up or down.
nPosition is a numeric value that indicates the position in the list of the item to select.
Select() is a method of the ListBox class that is used for changing the selected item in a list. Its state is typically changed when one of the arrow keys is pressed or the mouse's left button is pressed when its cursor is within the ListBox object's screen region. If necessary, Select() will call its display() method to ensure that the newly selected item is visible.
Note: When present, the scroll bar is automatically updated to reflect the new first visible item in the list when the call to ListBox:select() causes the list to be scrolled.
setData() Changes the data associated with a list item
oListBox:setData(nPosition, expValue) → self
nPosition is a numeric value that indicates the position of the item within the list whose data is being replaced.
expValue is the data that is being associated with the item specified by nPosition.
setData() is a method of the ListBox class that is used for changing the data that is associated with a list item.
setFocus() Gives input focus to the ListBox object
oListBox:setFocus() → self
setFocus() is a method of the ListBox class that is used for giving focus to a ListBox object. Upon receiving this message, the ListBox object redisplays itself and, if present, evaluates the code block within its fBlock variable.
This message is meaningful only when the ListBox object does not have input focus.
setItem() Replaces an item in a list
oListBox:setItem(nPosition, aItem) → self
nPosition is a numeric value that indicates the position of the item within the list which is being replaced.
aItem is the new list box item expressed as a two-element array consisting of the item's text and data respectively.
setItem() is a method of the ListBox class that is used for replacing an item in a list.
setText() Changes the text associated with a list item
oListBox:setText(nPosition, cText) → self
nPosition is a numeric value that indicates the position of the item within the list whose text is being replaced.
cText is a character string that indicates the new text for the item specified by nPosition.
setText() is a method of the ListBox class that is used for changing the text that is associated with a list item.
Examples
■ This example shows how the user can select the screen's
foreground color:
function SelectFore()
local cOldWindow, oList, nChoice
memvar GetList
cOldWindow := SaveScreen(5, 10, 12, 20)
oList := ListBox(5, 10, 12, 20, { | x | iif(x == NIL,;
nChoice, nChoice := x })
oList:addItem("Black", "N")
oList:addItem("Blue", "B")
oList:addItem("Green", "G")
oList:addItem("Cyan", "BG")
oList:addItem("Red", "R")
oList:addItem("Magenta", "RB")
oList:addItem("Brown", "GR")
oList:addItem("White", "W")
AAdd(GetList, oList)
read
RestScreen(5, 10, 12, 20, cOldWindow)
return (oList:GetData(nChoice))
exp list is the list of expressions to be evaluated and displayed for each record processed.
TO PRINTER echoes output to the printer.
TO FILExcFile echoes output to the specified file name and can be specified either as a literal file name or as a character expression enclosed in parentheses. If an extension is not specified, .txt is added.
scope is the portion of the current database file to LIST. The default is ALL records.
WHILElCondition specifies the set of records meeting the condition from the current record until the condition fails.
FORlCondition specifies the conditional set of records to LIST within the given scope.
OFF suppresses the display of record numbers.
Description
LIST is a console command that sequentially accesses records in the current work area, displaying the results of one or more expressions for each record accessed. The output is in tabular format with each column separated by a space. LIST is identical to DISPLAY with the exception that its default scope is ALL rather than NEXT 1.
When invoked, output is sent to the screen and, optionally, to the printer and/or a file. To suppress output to the screen while printing or echoing output to a file, SET CONSOLE OFF before the LIST invocation.
Notes
■ Interrupting LIST: So the user may interrupt a LIST, use
Inkey() as part of the FOR condition to test for an interrupt key press. See the example below.
■ Printer margin: LIST honors the current SET MARGIN for output
echoed to the printer.
Examples
■ In this example, a simple list is followed by a conditional
list to the printer:
USE Sales
LIST Date(), Time(), Branch
LIST Branch, Salesman FOR Amount > 500 TO PRINTER
■ This example interrupts LIST using Inkey() to test whether the
user pressed the Esc key:
#define K_ESC 27
USE Sales INDEX Salesman NEW
LIST Branch, Salesman, Amount WHILE Inkey() != K_ESC
Calculate the natural logarithm of a numeric value
Syntax
Log(<nExp>) → nNaturalLog
Arguments
nExp is a numeric value greater than zero to be converted to its natural logarithm.
Returns
Log() returns the natural logarithm as a numeric value. If nExp is less than or equal to zero, Log() returns a numeric overflow (displayed as a row of asterisks).
Description
Log() is a numeric function that calculates the natural logarithm of a number and is the inverse of Exp(). The natural logarithm has a base of e which is approximately 2.7183. The Log() function returns x in the following equation,
e**x = y
where y is the numeric expression used as the Log() argument (i.e., Log(y) = x). Due to mathematical rounding, the values returned by Log() and Exp() may not agree exactly (i.e., Exp(Log(x)) may not always equal x).
Examples
■ These examples demonstrate various results of Log():
? Log(10) // Result: 2.30
? Log(10 * 2) // Result: 3.00
? Exp(Log(1)) // Result: 1.00
? Log(2.71) // Result: 1.00
■ This example is a user-defined function that returns the base
10 logarithm:
FUNCTION Log10( nNumber )
IF nNumber > 0
RETURN Log(nNumber)/Log(10)
ELSE
RETURN NIL
ENDIF
cString is a character string to be converted to lowercase.
Returns
Lower() returns a copy of cString with all alphabetic characters converted to lowercase. All other characters remain the same as in the original string.
Description
Lower() is a character function that converts uppercase and mixed case strings to lowercase. It is related to Upper() which converts lowercase and mixed case strings to uppercase. Lower() is related to the IsLower() and IsUpper() functions which determine whether a string begins with a lowercase or uppercase letter.
Lower() is generally used to format character strings for display purposes. It can, however, be used to normalize strings for case- independent comparison or INDEXing purposes.
Examples
■ These examples demonstrate various results of Lower():
? Lower("STRING") // Result: string
? Lower("1234 CHARS = ") // Result: 1234 chars =
identifier is the name of a variable or array to declare local. If the identifier is followed by square brackets ([ ]), it is created as an array. If the identifier is an array, the syntax for specifying the number of elements for each dimension can be array[nElements, nElements2,...] or array[nElements][nElements2]... The maximum number of elements per dimension is 4096. The maximum number of dimensions per array is limited only by available memory.
initializer is the optional assignment of a value to a new local variable. Array identifiers, however, cannot be given values with an initializer. An initializer for a local variable consists of the inline assignment operator (:=) followed by any valid CA-Clipper expression including a literal array. If no explicit initializer is specified, the variable is given an initial value of NIL. In the case of an array, each element is NIL.
Note: The macro operator (&) cannot be used in a LOCAL declaration statement.
Description
LOCAL is a declaration statement that declares one or more variables or arrays local to the current procedure or user-defined function, and must occur before any executable statement including PRIVATE, PUBLIC, and PARAMETERS. Local variable declarations hide all inherited private variables and visible public variables with the same name. A LOCAL statement, however, that declares a variable name which is already declared causes a fatal compiler error and no object file (.OBJ) is generated. This error can happen as a result of two declarations for the same variable name in the same routine, or as the result of redeclaring a variable with filewide scope. Declaration statements include FIELD, MEMVAR, and STATIC.
Local variables are visible only within the current procedure or user- defined function and, unlike private variables, are not visible within invoked routines. Local variables are created automatically each time the procedure in which they were declared begins executing. They continue to exist and retain their values until the declaring procedure or user-defined function returns control to the code that invoked it. If a procedure or user-defined function is invoked recursively (calls itself), each recursive activation creates a new set of local variables.
The initial value of local variables and array elements is NIL if not explicitly initialized, either in the initializer list or by assignment. The initializer expression can be any valid CA-Clipper expression, including function calls. Note that an array declaration cannot have an initializer.
The maximum number of local variables in a program is limited only by available memory. Arrays, however, assigned to a local variable are still limited to 4096 elements per dimension.
For more information on variable declarations and scoping, refer to the Variables section in the "Basic Concepts" chapter of the Programming and Utilities Guide.
Notes
■ Inspecting local variables within the debugger: To access
local variable names within the CA-Clipper DOS-level debugger, you must compile program (.prg) files using the /B option so that local variable information is included in the object file.
■ Local parameters: Declare a list of local parameters as a part
of a FUNCTION or PROCEDURE declaration by enclosing the list of parameters in parentheses following the idFunction:
FUNCTIONidFunction(idParam list)
Declaration of local parameters supersedes creation of private parameters with the PARAMETERS statement.
■ Macro expressions: You cannot refer to local variables within
macro variables and expressions. If you refer to a local variable within a macro variable, a private or public variable with the same name will be referenced instead. If no such variable exists, a runtime error will be generated.
■ Memory files: Local variables cannot be SAVED to or RESTOREd
from memory (.mem) files.
■ Type of a local variable: Since Type() uses the macro operator
(&) to evaluate its argument, it cannot be used to determine the type of a local or static variable or an expression containing a local or static variable reference. The ValType() function provides this facility. ValType() evaluates its argument and returns the type of the return value.
Examples
■ This example declares two local arrays and two local
variables:
LOCAL aArray1[20, 10], aArray2[20][10], var1, var2
■ This example declares two local variables with initializers.
The first is initialized to a date value and the second to a literal
array:
LOCAL dWhen := Date()
LOCAL aVegies := {"Tomato", "Chickadee", "Butterbean"}
Search sequentially for a record matching a condition
Syntax
LOCATE [<scope>] FOR <lCondition>
[WHILE <lCondition>]
Arguments
scope is the portion of the current database file in which to perform the LOCATE. The default scope is ALL records.
FORlCondition specifies the next record to LOCATE within the given scope.
WHILElCondition specifies the set of records meeting the condition from the current record until the condition fails.
Description
LOCATE is a database command that searches for the first record in the current work area that matches the specified conditions and scope. When you first execute a LOCATE, it searches from the beginning record of the scope for the first matching record in the current work area. It terminates when a match is found or the end of the LOCATE scope is reached. If it is successful, the matching record becomes the current record and Found() returns true (.T.). If it is unsuccessful, Found() returns false (.F.) and the positioning of the record pointer depends on the controlling scope of the LOCATE.
Each work area can have its own LOCATE condition. The condition remains active until you execute another LOCATE command in that work area or the application terminates.
LOCATE works with CONTINUE. Once a LOCATE has been issued, you can resume the search from the current record pointer position with CONTINUE. There are, however, some exceptions. See note below.
Notes
■ CONTINUE: Both the scope and the WHILE condition apply only
to the initial LOCATE and are not operational for any subsequent CONTINUE commands. To continue a pending LOCATE with a scope or WHILE condition, use SKIP then LOCATE REST WHILElCondition instead of CONTINUE.
Examples
■ These examples show typical LOCATEs:
USE Sales INDEX Salesman
LOCATE FOR Branch = "200"
? Found(), Eof(), RecNo() // Result: .T. .F. 5
LOCATE FOR Branch = "5000"
? Found(), Eof(), RecNo() // Result: .F. .T. 85
■ This example shows a LOCATE with a WHILE condition that is
continued by using LOCATE REST:
SEEK "Bill"
LOCATE FOR Branch = "200" WHILE Salesman = "Bill"
DO WHILE Found()
? Branch, Salesman
SKIP
LOCATE REST FOR Branch = "200" WHILE ;
Salesman = "Bill"
ENDDO
cString is the character string to copy without leading spaces.
Returns
LTrim() returns a copy of cString with the leading spaces removed. If cString is a null string ("") or all spaces, LTrim() returns a null string ("").
Description
LTrim() is a character function that formats character strings with leading spaces. These can be, for example, numbers converted to character strings using Str().
LTrim() is related to RTrim(), which removes trailing spaces, and AllTrim(), which removes both leading and trailing spaces. The inverse of AllTrim(), LTrim(), and RTrim() are the PadC(), PadR(), and PadL() functions which center, right-justify, or left-justify character strings by padding them with fill characters.
Notes
■ Space characters: The LTrim() function treats carriage
returns, line feeds, and tabs as space characters and removes these as well.
Examples
■ These examples illustrate LTrim() used with several other
functions:
nNumber = 18
? Str(nNumber) // Result: 18
? Len(Str(nNumber)) // Result: 10
? LTrim(Str(nNumber)) // Result: 18
? Len(LTrim(Str(nNumber))) // Result: 2
Return the last modification date of a database (.dbf) file
Syntax
LUpdate() → dModification
Returns
LUpdate() returns the date of the last change to the open database file in the current work area. If there is no database file in USE, LUpdate() returns a blank date.
Description
LUpdate() is a database function that determines the date the database file in the current work area was last modified and CLOSEd. By default, LUpdate() operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression, as shown in the example below.
Examples
■ This example demonstrates that the modification date of the
database file is not changed until the database file is closed:
? Date() // Result: 09/01/90
USE Sales NEW
? LUpdate() // Result: 08/31/90
//
APPEND BLANK
? LUpdate() // Result: 08/31/90
CLOSE DATABASES
//
USE Sales NEW
? LUpdate() // Result: 09/01/90
■ This example uses an aliased expression to access LUpdate()
for a database file opened in an unselected work area:
USE Sales NEW
USE Customer NEW
? LUpdate(), Sales->(LUpdate())
nExp1 and nExp2 are the numeric values to be compared.
dExp1 and dExp2 are the date values to be compared.
Returns
Max() returns the larger of the two arguments. The value returned is the same type as the arguments.
Description
Max() is a numeric and date function that ensures the value of an expression is larger than a specified minimum. The inverse of Max() is Min(), which returns the lesser of two numeric or date values.
Examples
■ In these examples Max() returns the greater of two numeric
values:
? Max(1, 2) // Result: 2
? Max(2, 1) // Result: 2
■ In these examples Max() compares date values:
? Date() // Result: 09/01/90
? Max(Date(), Date() + 30) // Result: 10/01/90
? Max(Date(), CToD("")) // Result: 09/01/90
MaxCol() returns the column number of the rightmost visible column for display purposes.
Description
MaxCol() is a screen function that determines the maximum visible column of the screen. Row and column numbers start at zero in CA-Clipper.
If you use a C or other extended function to set the video mode, use the SetMode() function so your CA-Clipper application returns the correct value for MaxCol().
Examples
■ This example uses MaxRow() and MaxCol() to determine the area
in which to draw a box, and then executes dbEdit() within the box
region:
CLS
@ 0, 0 TO MaxRow(), MaxCol() DOUBLE
dbEdit(1, 1, MaxRow() + 1, MaxCol() - 1)
MaxRow() returns the row number of the bottommost visible row for display purposes.
Description
MaxRow() is a screen function that determines the maximum visible row of the screen. Row and column numbers start at zero in CA-Clipper.
If you use a C or other extended function to set the video mode, use the SetMode() function so your CA-Clipper application returns the correct value for MaxCol().
Examples
■ This user-defined function, ScreenSize(), uses MaxRow() and
MaxCol() to return an array containing the current screen size:
FUNCTION ScreenSize
RETURN { MaxRow(), MaxCol() }
Determine the mouse cursor's screen column position
Syntax
MCol() → nCurrentMouseColumn
Returns
MCol() returns the mouse cursor's current screen column position.
Description
MCol() is a function that is used for determining the mouse cursor's screen column position. This is useful when implementing a hit testing routine whose purpose is to determine if the mouse cursor is on pertinent information when the left mouse button is pressed.
Determine the double-click speed threshold of the mouse
Syntax
MDblClk([<nNewSpeed>]) → nSpeed
Arguments
nNewSpeed is the maximum allowable amount of time between mouse key presses for a double-click to be detected. This is measured in milliseconds.
Returns
MDblClk() returns the current double-click speed threshold.
Description
MDblClk() is a function used for determining and, optionally, changing the mouse's double-click speed threshold. This is useful when the mouse's double-click sensitivity needs to be adjusted.
cString is the character string or memo field to copy to the MemoEdit() text buffer. If not specified, the text buffer is empty.
nTop, nLeft, nBottom, and nRight are the upper-left and lower-right window coordinates. Row values can range from zero to MaxRow(), and column positions can range from zero to MaxCol(). If not specified, the default coordinates are 0, 0, MaxRow(), and MaxCol().
lEditMode determines whether the text buffer can be edited or merely displayed. Specifying true (.T.) allows the user to make changes to the text buffer, while specifying false (.F.) only allows the user to browse the text buffer. If not specified, the default value is true (.T.).
cUserFunction is the name of a user-defined function that executes when the user presses a key not recognized by MemoEdit() and when no keys are pending in the keyboard buffer. cUserFunction is specified as a character value without parentheses or arguments. Specifying false (.F.) for this argument displays cString and causes MemoEdit() to immediately terminate. If this argument is specified, the automatic behavior of MemoEdit() changes. Refer to the discussion below.
nLineLength determines the length of lines displayed in the MemoEdit() window. If a line is greater than nLineLength, it is word wrapped to the next line in the MemoEdit() window. If nLineLength is greater than the number of columns in the MemoEdit() window, the window will scroll if the cursor moves past the window border. If nLineLength is not specified, the default line length is (nRight - nLeft).
nTabSize determines the tab stops that will be used when the user presses Tab. If nTabSize is not specified, tab stops will be placed at every four characters.
nTextBufferRow and nTextBufferColumn define the display position of the cursor within the text buffer when MemoEdit() is invoked. nTextBufferRow begins with one (1) and nTextBufferColumn begins with zero (0). If these arguments are not specified, the cursor is placed at row one (1) and column zero (0) of the MemoEdit() window.
nWindowRow and nWindowColumn define the initial position of the cursor within the MemoEdit() window. Row and column positions begin with zero (0). If these arguments are not specified, the initial window position is row zero (0) and the current cursor column position.
Returns
MemoEdit() returns the text buffer if the user terminates editing with Ctrl+W or a copy of cString if user terminates with Esc.
Description
MemoEdit() is a user interface and general purpose text editing function that edits memo fields and long character strings. Editing occurs within a specified window region placed anywhere on the screen. Like the other user interface functions (AChoice() and dbEdit()), MemoEdit() supports a number of different modes and includes a user function that allows key reconfiguration and other activities relevant to programming the current text editing task.
■ The text buffer: When you invoke MemoEdit() and specify
cString, it is copied to the text buffer. The user actually edits the text buffer. If the cString is not specified, the user is presented with an empty text buffer to edit.
When the user exits MemoEdit() by pressing Ctrl+W, the contents of the text buffer are returned. If the user exits by pressing Esc, the text buffer is discarded and the original cString value is returned. In either case, the return value can then be assigned to a variable or memo field, or passed as an argument to another function.
■ Editing modes: MemoEdit() supports two editing modes depending
on the value of lEditMode. When lEditMode is true (.T.), MemoEdit() enters edit mode and the user can change the contents of the MemoEdit() text buffer. When lEditMode is false (.F.), MemoEdit() enters browse mode and the user can only navigate about the text buffer but cannot edit or insert new text. To make browsing easier for the user, the scrolling is disabled so Up arrow and Down arrow scroll the text buffer up or down one line within the MemoEdit() window.
■ Entering and editing text: Within MemoEdit(), the user can
enter and edit text by positioning the cursor, adding, or deleting characters. To facilitate editing the text, there are a number of different navigation and editing keys:
MemoEdit() Navigation and Editing Keys
Key Action
Up arrow/Ctrl+E Move up one line
Down arrow/Ctrl+X Move down one line
Left arrow/Ctrl+S Move left one character
Right arrow/Ctrl+D Move right one character
Ctrl+Left arrow/Ctrl+A Move left one word
Ctrl+Right arrow/Ctrl+F Move right one word
Home Move to beginning of current line
End Move to end of current line
Ctrl+Home Move to beginning of current window
Ctrl+End Move to end of current window
PgUp Move to previous edit window
PgDn Move to next edit window
Ctrl+PgUp Move to beginning of memo
Ctrl+PgDn Move to end of memo
Return Move to beginning of next line
Delete Delete character at cursor
Backspace Delete character to left of cursor
Tab Insert tab character or spaces
Printable characters Insert character
Ctrl+Y Delete the current line
Ctrl+T Delete word right
Ctrl+B Reform paragraph
Ctrl+V/Ins Toggle insert mode
Ctrl+W Finish editing with save
Esc Abort edit and return original
When the user is entering text, there are two text entry modes, insert and overstrike. When MemoEdit() is invoked, the default mode is overstrike. Edit mode changes in MemoEdit() when the user presses Ins which toggles between the insert and overstrike. It also changes in a user function using ReadInsert() or RETURNing 22. In insert mode, characters are entered into the text buffer at the current cursor position and the remainder of the text moves to the right. Insert mode is indicated in the scoreboard area. In overstrike mode, characters are entered at the current cursor position overwriting existing characters while the rest of the text buffer remains in its current position.
As the user enters text and the cursor reaches the edge of the MemoEdit() window, the current line wraps to the next line in the text buffer and a soft carriage return (Chr(141)) is inserted into the text. If the nLineLength argument is specified, text wraps when the cursor position is the same as nLineLength. If nLineLength is greater than the width of the MemoEdit() window, the window scrolls. To explicitly start a new line or paragraph, the user must press Return.
■ The edit screen: When MemoEdit() displays, it overwrites the
specified area of the screen and does not save the underlying screen. Additionally, it does not display a border or a title. To provide these facilities, you must create a procedure or user-defined function that performs these actions, and then calls MemoEdit(). See the example below.
■ The user function: cUserFunction, a user-defined function
specified as an argument, handles key exceptions and reconfigures special keys. The user function is called at various times by MemoEdit(), most often in response to keys it does not recognize. Keys that instigate a key exception are all available control keys, function keys, and Alt keys. Since these keys are not processed by MemoEdit(), they can be reconfigured. Some of these keys have a default action assigned to them. In the user function, you perform various actions depending on the current MemoEdit() mode, and then RETURN a value telling MemoEdit() what to do next.
When the user function argument is specified, MemoEdit() defines two classes of keys: nonconfigurable and key exceptions. When a nonconfigurable key is pressed, MemoEdit() executes it; otherwise, a key exception is generated and the user function is called. When there are no keys left in the keyboard buffer for MemoEdit() to process, the user function is called once again.
When MemoEdit() calls the user function, it automatically passes three parameters indicating the MemoEdit() mode, the current text buffer line, and the current text buffer column. The mode indicates the current state of MemoEdit() depending on the last key pressed or the last action taken prior to executing the user function. The following modes are possible:
MemoEdit() Modes
Mode Memoedit.ch Description
0 ME_IDLE Idle, all keys processed
1 ME_UNKEY Unknown key, memo unaltered
2 ME_UNKEYX Unknown key, memo altered
3 ME_INIT Initialization mode
A mode value of 3 indicates that MemoEdit() is in initialization mode. When you specify cUserFunction, MemoEdit() makes a call to the user function immediately after being invoked. At this point, you RETURN a request to set MemoEdit()'s various text formatting modes: word wrap, scroll, or insert. MemoEdit() calls the user function repeatedly, remaining in the initialization mode until you RETURN 0. The text buffer is then displayed, and the user enters the edit mode set by lEditMode. Note that if word wrap is on when MemoEdit() changes from initialization to edit mode, the entire text buffer is formatted with nLineLength. To prevent this initial formatting, toggle word wrap off during initialization. Note also that the toggles for scroll and word wrap are not assigned to any key, but can be assigned to a key from the user function.
Modes 1 and 2 indicate that MemoEdit() has fetched an unrecognizable or configurable key from the keyboard buffer. Configurable keys are processed by RETURNing 0 to execute the MemoEdit() default action. RETURNing a different value executes another key action, thereby redefining the key. If the key is an unrecognizable key, you can define an action for it by RETURNing a value requesting a key action or perform an action of your own definition.
Mode 0 indicates that MemoEdit() is now idle with no more keys to process. Whenever MemoEdit() becomes idle, it always make a call to the user function. At this point, you generally update line and column number displays.
The other two parameters, current line and column, indicate the current cursor position in the text buffer when the user function is called. The line parameter begins with position one (1), and column begins with position zero (0).
When the mode is either 1, 2, or 3, you can return a value instructing MemoEdit() what action to perform next. The following table summarizes the possible return values and their consequences:
MemoEdit() User Function Return Values
Value Memoedit.ch Action
0 ME_DEFAULT Perform default action
1-31 ME_UNKEY Process requested action corresponding to
key value
32 ME_IGNORE Ignore unknown key
33 ME_DATA Treat unknown key as data
34 ME_TOGGLEWRAP Toggle word wrap mode
35 ME_TOGGLESCROLL Toggle scroll mode
100 ME_WORDRIGHT Perform word-right operation
101 ME_BOTTOMRIGHT Perform bottom-right operation
■ Header files: To make the mode and request values easier to
remember and use, the header file memoedit.ch is supplied in \CLIP53\INCLUDE. Additionally, inkey.ch, which contains manifest constants for all the Inkey() values, is also located in the same directory.
Notes
■ Configuring keys: If the cUserFunction is specified, the
keys in the table below are configurable.
MemoEdit() Configurable Keys
Key Default Action
Ctrl+Y Delete the current line
Ctrl+T Delete word right
Ctrl+B Reform Paragraph
Ctrl+V/Ins Toggle insert mode
Ctrl+W Finish editing with save
Esc Abort edit and return original
If the key is configurable, RETURNing 0 executes the MemoEdit() default action. RETURNing a different value, however, executes another key action thereby redefining the key. If the key is not a configurable key recognized by MemoEdit(), you can define an action for it also by RETURNing a value requesting a key action from the table above.
■ Word wrap: Word wrap is a formatting mode you can toggle by
RETURNing 34 from the user function. When word wrap is on (the default setting), MemoEdit() inserts a soft carriage return/line feed at the closest word break to the window border or line length, whichever occurs first. When word wrap is off, MemoEdit() scrolls text buffer beyond the edge of the window until the cursor reaches the end of line. At this point, the user must press Return (inserting a hard carriage return/line feed) to advance to the next line.
■ Reforming paragraphs: Pressing Ctrl+B or RETURNing a 2 from a
user function reformats the text buffer until a hard carriage return (end of paragraph) or the end of the text buffer is reached. This happens regardless of whether word wrap is on or off.
■ Soft carriage returns: In CA-Clipper, the insertion of soft
carriage return/linefeed characters is never allowed to change the significant content of the text. That is, when a soft carriage return/linefeed is inserted between two words, the space characters between the two words are preserved. When text is reformatted, any soft carriage return/linefeed characters are removed. This leaves the text in its original form and properly handles the case where a soft carriage return/linefeed has been inserted in the middle of a word.
In the Summer '87 version of MemoEdit(), when a soft carriage return/line feed is inserted, a single space character is removed from the text at that point. If the text is later reformatted using a different line width, each soft carriage return/linefeed is replaced by a single space. However, if the text string is reformatted using any of the CA-Clipper text handling functions, words that were separated by a soft carriage return/linefeed will be run together because the soft carriage return/linefeed is not replaced with a space.
To prevent this, text that was formatted using Summer '87 MemoEdit() should be processed to change any soft carriage return/linefeed pairs into space characters. This can be accomplished using the StrTran() function as follows:
StrTran( text, Chr(141)+Chr(10), " " )
To convert memo values in an existing database, the following two line program can be used:
USExcDatabaseREPLACE ALLidMemoWITH ;
StrTran( idMemo, Chr(141)+Chr(10), " " )
Because of the .dbt file format, replacing all occurrences of a memo field can cause the .dbt file to grow significantly. The .dbt file can be reduced by copying the .dbf to a new file.
For very large .dbt files, it may not be feasible to perform the above procedure. The supplied utility program, DBT50.EXE located in \CLIP53\BIN, may be useful in these cases. DBT50 scans an entire .dbt file, replacing any soft carriage return/line feed pairs with two spaces. Although this has the undesirable effect of causing certain words to be separated by two spaces instead of one, it allows the file to be processed in place without using additional disk space. DBT50 modifies only soft carriage return/linefeed pairs in the target file. Other text is unaffected.
■ Editing text files: MemoEdit() edits text files if the text
file can be read into a CA-Clipper character variable. This can be done with the MemoRead() function. After editing the contents of the text file held in the character variable, write it back to the file using MemoWrit().
Examples
■ This example lets you browse a memo field but prevents any
changes to the text buffer:
USE Customer NEW
SET CURSOR OFF
MemoEdit(CustNotes, 5, 10, 20, 69, .F.)
SET CURSOR ON
■ This example allows editing of a memo field, assigning the
changes back to the memo field:
USE Customer NEW
REPLACE CustNotes WITH ;
MemoEdit(CustNotes, 5, 10, 20, 69)
■ This example creates a character string using MemoEdit():
LOCAL cNotes
cNotes = MemoEdit()
■ This example is a user-defined function that edits a character
string in a boxed window displayed with a title:
FUNCTION EditMemo( cString, cTitle,;
nTop, nLeft, nBottom, nRight )
LOCAL cScreen := SaveScreen(nTop, nLeft,;
nBottom, nRight)
@ nTop - 1, nLeft - 2 CLEAR TO nBottom + 1,;
nRight + 2
@ nTop - 1, nLeft - 2 TO nBottom + 1, nRight + 2
@ nTop - 1, nLeft SAY "[" + cTitle + "]"
cString = MemoEdit(cString, nTop, nLeft,;
nBottom, nRight)
RestScreen(nTop, nLeft, nBottom, nRight, cScreen)
RETURN (cString)
■ This example reads the contents of a text file into a
character variable, edits it, and then writes it back to disk:
LOCAL cString := MemoRead("Text.txt")
cString := MemoEdit(cString)
IF !MemoWrit("Text.txt", cString)
? "Write error"
BREAK
ENDIF
RETURN
■ This example contains a user-defined function that displays a
message describing the current MemoEdit() mode. Additionally, while
in ME_UNKEY mode, the function will perform either a ME_WORDRIGHT or
ME_BOTTOMRIGHT action depending on which associated function key is
pressed:
#include "Memoedit.ch"
#include "Inkey.ch"
PROCEDURE Main()
USE Customer NEW
REPLACE CustNotes WITH;
MemoEdit( CustNotes, 5, 5, 15, 75, .T., "MemoUDF" )
RETURN
FUNCTION MemoUDF( nMode, nLine, nCol )
LOCAL nKey := LastKey()
LOCAL nRetVal := ME_DEFAULT // Default return action
DO CASE
CASE nMode == ME_IDLE
@ 20, 5 SAY "MemoMode is ME_IDLE "
CASE nMode == ME_UNKEY
@ 20, 5 SAY "MemoMode is ME_UNKEY "
DO CASE
CASE nKey == K_F2
nRetVal := ME_WORDRIGHT
CASE nKey == K_F3
nRetVal := ME_BOTTOMRIGHT
ENDCASE
CASE nMode == ME_UNKEYX
@ 20, 5 SAY "MemoMode is ME_UNKEYX"
OTHERWISE
@ 20, 5 SAY "MemoMode is ME_INIT "
ENDCASE
RETURN nRetVal
cString is the memo field or character string from which a line of text is to be extracted.
nLineLength specifies the number of characters per line and can be between four and 254. If not specified, the default line length is 79.
nLineNumber is the line number to be extracted. If not specified, the default value is one.
nTabSize defines the tab size. If not specified, the default value is four. If nTabSize is greater than or equal to nLineLength, then the tab size is automatically converted to nLineLength - 1.
lWrap toggles word wrap on and off. Specifying true (.T.) toggles word wrap on; false (.F.) toggles it off. If not specified, the default value is true (.T.).
Returns
MemoLine() returns the line of text specified by nLineNumber in cString as a character string. If the line has fewer characters than the indicated length, the return value is padded with blanks. If the line number is greater than the total number of lines in cString, MemoLine() returns a null string ("").
If lWrap is true (.T.) and the indicated line length breaks the line in the middle of a word, that word is not included as part of the return value but shows up at the beginning of the next line extracted with MemoLine().
If lWrap is false (.F.), MemoLine() returns only the number of characters specified by the line length. The next line extracted by MemoLine() begins with the character following the next hard carriage return, and all intervening characters are not processed.
Description
MemoLine() is a memo function used with MLCount() to extract lines of text from character strings and memo fields based on the number of characters per line. It is the most basic facility provided by CA-Clipper to display memo fields and long strings.
The basic method of operation is to determine the number of lines in the memo field or character string using MLCount() with the same number of characters per line, tab size, and wrapping behavior as you intend to use with MemoLine(). Using this value as the upper boundary of a FOR...NEXT, each line of the memo field or character string can be extracted with MemoLine() and processed with any combination of output commands and functions required.
Examples
■ This example demonstrates the general method for displaying
memo fields and long character strings using the combination of
MLCount() and MemoLine():
LOCAL nLineLength := 40, nTabSize := 3, lWrap := .T.
LOCAL nLines, nCurrentLine
USE Customer INDEX CustName NEW
//
nLines := MLCount(CustNotes, nLineLength,;
nTabSize, lWrap)
//
SET PRINTER ON
FOR nCurrentLine := 1 TO nLines
? MemoLine(CustNotes, nLineLength, nCurrentLine,;
nTabSize, lWrap)
NEXT
SET PRINTER OFF
Determine the amount of available free pool memory
Syntax
Memory(<nExp>) → nKbytes
Arguments
nExp is a numeric value that determines the type of value Memory() returns as follows:
Memory() Argument Values
Value Meaning
0 Estimated total space available for character values
1 Largest contiguous block available for character values
2 Area available for RUN commands
Returns
Memory() returns an integer numeric value representing the amount of memory available, in one -kilobyte increments.
Description
Memory() is an environment function that reports various states of free pool memory. (Free pool is the dynamic region of memory that stores character strings and executes RUN commands.)
Examples
■ This example uses Memory() before a RUN command to determine
if there is enough memory available to execute the external program:
#define MEM_CHAR 0
#define MEM_BLOCK 1
#define MEM_RUN 2
//
IF Memory(MEM_RUN) >= 128
RUN MYPROG
ELSE
? "Not enough memory to RUN"
BREAK
ENDIF
Return the contents of a disk file as a character string
Syntax
MemoRead(<cFile>) → cString
Arguments
cFile is the name of the file to read from disk. It must include an extension, if there is one, and can optionally include a path.
Returns
MemoRead() returns the contents of a text file as a character string. The maximum file size that can be read is 65,535 characters (64K)—the maximum size of a character string. If cFile cannot be found, MemoRead() returns a null string ("").
Description
MemoRead() is a memo function that reads a disk file into memory where it can be manipulated as a character string or assigned to a memo field. MemoRead() is used with MemoEdit() and MemoWrit() to edit an imported disk file, and then write it back to disk. MemoRead() searches for cFile beginning with the current DOS directory. If the file is not found, MemoRead() searches the DOS path. MemoRead() does not use the CA-Clipper DEFAULT or PATH to search for cFile.
In a network environment, MemoRead() attempts to open the specified file shared and read—only. If the file is opened exclusive by another process, MemoRead() returns a null string ("").
Examples
■ This example uses MemoRead() to assign the contents of a text
file to the Notes memo field and to a character variable:
REPLACE Notes WITH MemoRead("Temp.txt")
cString = MemoRead("Temp.txt")
■ This example defines a function that edits a disk file:
FUNCTION Editor( cFile )
LOCAL cString
IF (cString := MemoRead(cFile)) == ""
? "Error reading " + cFile
RETURN .F.
ELSE
MemoWrit(cFile, MemoEdit(cString))
RETURN .T.
ENDIF
cString is the character string or memo field to be searched.
cReplaceHardCR is the character with which to replace a hard carriage return/line feed pair. If not specified, the default value is a semicolon (;).
cReplaceSoftCR is the character with which to replace a soft carriage return/line feed pair. If not specified, the default value is a space.
Returns
MemoTran() returns a copy of cString with the specified carriage return/line feed pairs replaced.
Description
MemoTran() is a memo function that converts a memo field or long character string containing hard and soft carriage return/line feed characters into a form that can be displayed. These two character combinations are end of line formatting indicators placed in the string by MemoEdit(). Soft carriage returns (Chr(141)) are inserted when a line longer than the width of the MemoEdit() window wraps. Hard carriage returns (Chr(13)) are inserted when the user explicitly presses Return.
MemoTran() is particularly useful when displaying a memo field in a REPORT FORM which does not wrap when a soft carriage return is encountered. MemoTran() resolves this by converting soft carriage returns to spaces. Note, however, that you must declare MemoTran() as external using the REQUEST statement if it is used in a REPORT FORM and not specified anywhere else in the current program.
Examples
■ This example strips all end of line characters from a memo
field:
REPLACE Notes WITH MemoTran(Notes)
Write a character string or memo field to a disk file
Syntax
MemoWrit(<cFile>, <cString>) → lSuccess
Arguments
cFile is the name of the target disk file including the file extension and optional path and drive designator.
cString is the character string or memo field to write to cFile.
Returns
MemoWrit() returns true (.T.) if the writing operation is successful; otherwise, it returns false (.F.).
Description
MemoWrit() is a memo function that writes a character string or memo field to a disk file. If a path is not specified, MemoWrit() writes cFile to the current DOS directory and not the current DEFAULT directory. If cFile already exists, it is overwritten.
MemoWrit() is generally used with MemoRead() to load text files into memory where they can be edited, displayed, and written back to disk. You can also use MemoWrit() as a quick way of exporting a memo field to a text file.
Examples
■ This example uses MemoWrit() with MemoRead() to allow editing
of memo fields with an external editor:
LOCAL cEditor := "MYEDIT.EXE"
USE Sales NEW
IF MemoWrit("Cliptmp.txt", Notes)
RUN (cEditor + " Cliptmp.txt")
REPLACE Notes WITH MemoRead("Cliptmp.txt")
ELSE
? "Error while writing Cliptmp.txt"
BREAK
ENDIF
Return a set-get code block for a given memory variable
Syntax
MemVarBlock(<cMemvarName>) → bMemvarBlock
Arguments
cMemvarName is the name of the variable referred to by the set-get block, specified as a character string.
Returns
MemVarBlock() returns a code block that when evaluated sets (assigns) or gets (retrieves) the value of the given memory variable. If cMemvarName does not exist, MemVarBlock() returns NIL.
Description
The code block created by MemVarBlock() has two operations depending on whether an argument is passed to the code block when it is evaluated. If evaluated with an argument, it assigns the value of the argument to cMemvarName. If evaluated without an argument, the code block retrieves the value of cMemvarName.
Notes
■ MemVarBlock() creates set-get blocks only for variables whose
names are known at runtime. MemVarBlock(), therefore, cannot be used to create set-get blocks for local or static variables. The same restriction applies to creating blocks using the macro operator (&).
Examples
■ This example compares MemVarBlock() to a code block created
using the macro operator (&). Note that using MemVarBlock() allows
you to avoid the speed and size overhead of the macro operator:
PRIVATE var := "This is a string"
//
// Set-Get block defined using macro operator
bSetGet := &( "{ |setVal|;
IF( setVal == NIL, var, var := setVal ) }" )
// Set-Get block defined using MemVarBlock()
// bSetGet created here is the functional
// equivalent of bSetGet above
bSetGet := MemVarBlock("var")
MenuItem objects are the basis for which both top bar and pop-up menus are built upon.
Methods link
Class Function
MenuItem() Create a new MenuItem object
MenuItem(cCaption, expData, [nShortcut],
[cMessage], [nID]) → oMenuItem
Arguments
cCaption is a character string that contains either a text string that concisely describes the menu option or a menu separator specifier. This value is assigned to the MenuItem:caption instance variable.
expData is a value that contains either a code block or a PopUpMenu object. This argument is ignored when cCaption contains a menu separator specifier. This value is assigned to the MenuItem:data instance variable.
nShortcut is an optional numeric inkey value that indicates the shortcut key combination that selects and launches the menu selection. The default is 0. This value is assigned to the MenuItem:shortcut instance variable. Constant values for various key combinations are defined in inkey.ch.
cMessage is an optional character string that indicates the text to display on the status bar when the menu item is selected. The default is an empty string. This value is assigned to the MenuItem:message instance variable.
nID is an optional numeric value that uniquely identifies the menu item. The default is 0. This value is assigned to the MenuItem:id instance variable.
Returns
Returns a MenuItem object when all of the required arguments are present; otherwise, MenuItem() returns NIL.
Exported Instance Variables
caption Describes menu option or menu separator
caption (Assignable)
Contains either a text string that concisely describes the menu option or a menu separator specifier. MenuItem:caption is the text that appears in the actual menu.
A menu separator is a horizontal line in a pop-up menu that separates menu items into logical groups. Use the constant MENU_SEPARATOR in button.ch to assign the menu separator specifier to MenuItem:caption.
When present, the & character specifies that the character immediately following it in the caption is the menu item's accelerator key. The accelerator key provides a quick and convenient mechanism for the user to select a menu item when the menu that it is contained within has input focus. When the menu is a member of a TopBarMenu object, the user selects the menu item by pressing the Alt key in combination with the accelerator key. When the menu is a member of a PopUpMenu object, the user selects the menu item by simply pressing the accelerator key. The accelerator key is not case sensitive.
cargo User-definable variable
cargo (Assignable)
Contains a value of any type that is ignored by the MenuItem object. MenuItem:cargo is provided as a user-definable slot allowing arbitrary information to be attached to a MenuItem object and retrieved later.
checked Logical value which indicates a check mark
checked (Assignable)
Contains a logical value that indicates whether a check mark appears to the left of the menu item's caption. A value of true (.T.) indicates that a check mark should show; otherwise, a value of false (.F.) indicates that it should not.
data Contains code block or a PopUpMenu object
data (Assignable)
Contains either a code block or a PopUpMenu object or, when the menu item's Caption property contains a menu separator specifier, MenuItem:data contains NIL. When the menu item is selected, its code block, if present, is evaluated; otherwise, its PopUpMenu object is opened.
enabled Logical value indicating if menu item is selected
enabled (Assignable)
Contains a logical value that indicates whether the menu item can be selected or not. MenuItem:enabled contains true (.T.) to permit user access; otherwise, it contains false (.F.) to deny user access. When disabled, the item will be shown in its disabled color.
id Numeric value which identifies the menu item
id (Assignable)
Contains an optional numeric value that uniquely identifies the menu item. The default is 0. This value is returned by MenuModal() to indicate the selected menu item.
message String that describes the menu item
message (Assignable)
Contains an optional string that describes the menu item. This is the text that appears on the screen's status bar line. The default is an empty string. The MenuModal() function defines the row and width for the area on the screen where messages are displayed.
shortcut Numeric value indicating the key to activate menu selection
shortcut (Assignable)
Contains an optional numeric inkey value indicating the key that activates the menu selection. The default is 0. Shortcut keys are available only for menu items on a PopUpMenu. TopBarMenu items cannot have shortcut keys associated with them.
The shortcut key name automatically appears to the right of the MenuItem:caption. Unlike with an accelerator key, the menu need not be open for the shortcut key to be active.
style String indicating the characters used by PopUpMenu:display()
style (Assignable)
Contains a character string that indicates the delimiter characters that are used by the PopUpMenu:display() method. The string must contain two characters. The first is the character associated with the MenuItem:checked property. Its default value is the square root character. The second is the submenu indicator. Its default is the right arrow character.
Exported Methods
isPopUp() Indicates whether MenuItem:data contains a PopUpMenu object
oMenuItem:isPopUp() → lPopUpStatus
Returns a logical value that indicates whether the menu item's data property contains a pop-up menu. A value of true (.T.) indicates that MenuItem:data contains a PopUpMenu object; otherwise, a value of false (.F.) indicates that it does not.
isPopUp() is a method of the MenuItem class that is used for determining whether a menu item is a branch in a menu tree. When a menu item is selected, typically one of two results will occur. If it is a menu tree branch, its pop-up menu is opened; otherwise, its code block will be evaluated.
Examples
See the Menu.prg sample file in the \CLIP53\SOURCE\SAMPLE directory.
This example demonstrates combining TopBarMenu, PopUpMenu, and MenuItem
objects to create a menu with a number of available choices. See
"Introduction to the Menu System" in the Programming and Utilities Guide
for more information about using this class.
oTopBar is a TopBarMenu object created from the TopBarMenu class.
nSelection is the TopBarMenu item selected by default.
nMsgRow is the row number where menu item messages will appear.
nMsgLeft specifies the left border for menu item messages.
nMsgRight specifies the right border for menu item messages.
cMsgColor defines the color string for the menu item messages. It consists of a single foreground/background pair.
Returns
MenuModal() returns the menu ID of the chosen menu item. Menu IDs are assigned using the MenuItem class.
Description
MenuModal() is a user-interface function that implements the pull-down menu system in CA-Clipper. It is part of the open architecture Get system of CA-Clipper. MenuModal() is similar to the READ command in that it waits for the user to perform an action. However, the MenuModal() function will only respond to menu actions.
To implement a menu object at the same time as other objects, use the ReadModal() function which has one of its arguments as TopBarMenu object.
When the user chooses a menu item, control is passed to the code block associated with that particular menu item. Code blocks are defined using the MenuItem class.
The menu items can be selected by using either the keyboard or the mouse. To select a menu item with the mouse, simply select its TopBarMenu item with the mouse and then choose the appropriate PopUp menu item.
Note: The MenuModal() function will take one menu event from the user and then terminate. To avoid this, the following can be used, and the same will allow the program to continuously accept menu events:
DO WHILE (MenuModal(themenu,...) <> ExitMenu) ENDDO
The following table lists the active keys that can be used during MenuModal():
MenuModal() Navigation Keys
Key Action
Left arrow, Ctrl+S Move to the next TopBarMenu item to the left. If
there are no more items to the left, the rightmost
TopBarMenu item will be selected.
Right arrow, Ctrl+D Move to the next TopBarMenu item to the right. If
there are no more items to the right, the leftmost
TopBarMenu will be selected.
Up arrow, Ctrl+E Move to the previous PopUp menu item. If there are
no more items above the current item, the menu item
on the bottom will be selected.
Down arrow, Ctrl+X Move to the next PopUp menu item. If there are no
more items below the current item, the menu item on
the top will be selected.
Examples
See the Menu.prg sample file in the \CLIP53\SOURCE\SAMPLE directory.
This example demonstrates combining TopBarMenu, PopUpMenu, and MenuItem
objects to create a menu with a number of available choices. See
"Introduction to the Menu System" in the Programming and Utilities Guide
for more information about using this function.
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, source file is SOURCE/SYS/MENUSYS.PRG
Set an RDD inheritance chain for the DBFMEMO database driver
Syntax
MEMOSETSUPER([<cSuperRDD>]) → cOldSuperName
Arguments
cSuperRDD is a character string representing the name of the RDD from which DBFMEMO will inherit.
Returns
MEMOSETSUPER() always returns NIL.
Description
The DBFMEMO driver is only capable of handling commands and functions that relate to memo fields. Therefore, it must inherit the non-memo database characteristics (such as SKIP, REPLACE, SEEK, etc.) from a "super" driver (such as DBFNTX).
For example, the DBFCDX RDD is nothing more than the DBFMEMO RDD hardwired to inherit database characteristics from the _DBFCDX RDD. That is, when you use the DBFCDX RDD, you are using the DBFMEMO driver to handle the memo field operations and you are using the _DBFCDX driver to handle the other database and index operations as the "super" driver.
At times, you may want to use a database driver such as DBFNTX instead of DBFCDX but, at the same time, have the efficient and enhanced memo field capabilities of the DBFMEMO RDD instead of the DBT memo file format. In order to do this, you would use MEMOSETSUPER().
Warning! The MEMOSETSUPER() function can only set one inheritance chain per application instance. That is, once you have set MEMOSETSUPER() in an application, MEMOSETSUPER() cannot be changed. Doing so will have unpredictable results.
Examples
■ This example uses MEMOSETSUPER() to create a database (.dbf)
file with an .fpt/.dbv memo field:
REQUEST DBFMEMO
// Set the default to DBFMEMO
rddSetDefault( "DBFMEMO" )
// Make DBFMEMO inherit from DBFNTX
MEMOSETSUPER( "DBFNTX" )
// Create a DBF with an FPT/DBV not DBT
dbCreate( "test.dbf", {{"notes", "M", 10, 0}} )
// Open DBF with FPT/DBV
// Indexes created would be NTX if created
USE test NEW
idMemvar list is a list of public and private variable names to declare to the compiler.
Description
MEMVAR is a declaration statement that causes the compiler to resolve references to variables specified without an explicit alias by implicitly assuming the memory variable alias (MEMVAR->). Only explicit, unaliased references to the specified variables are affected. MEMVAR, like all declaration statements, has no effect on references made within macro expressions or variables.
The MEMVAR statement neither creates the variables nor verifies their existence. Its primary effect is to ensure correct references to variables whose existence is known to be guaranteed at runtime. At runtime, the specified variables must be created using the PRIVATE, PARAMETERS or PUBLIC statements. This can occur in the procedure containing the MEMVAR declaration or in a higher -level procedure. Attempting to access the variables before they are created will cause an error.
The scope of the MEMVAR declaration is the procedure or function in which it occurs, or the entire source file if it precedes any PROCEDURE or FUNCTION statements and the /N compiler option is used. The /N option suppresses automatic definition of a procedure with the same name as the program (.prg) file.
Like other declaration statements, MEMVAR must precede any executable statements, including PARAMETERS, PUBLIC, and PRIVATE statements in a procedure or function definition, or the program (.prg) file if the declaration has filewide scope.
MEMVAR can be used in conjunction with the /W compiler option—which generates warning messages for ambiguous variable references—to perform compile—time checking for undeclared variables.
For more information on variable declarations and scoping, refer to the Variables section in the "Basic Concepts" chapter of the Programming and Utilities Guide.
Examples
■ This example demonstrates the relationship between a private
and field variable with the same name. The private variable is
declared with the MEMVAR statement:
FUNCTION Example
MEMVAR amount, address
PRIVATE amount := 100
USE Customer NEW
//
? amount // Refers to amount private variable
? Customer->Amount // Refers to Amount field variable
//
RETURN NIL
idVar is the name of the variable to be assigned the result of the menu selection. If the specified variable is not visible or does not exist, a private variable is created and assigned the result.
Description
MENU TO is the selection mechanism for the CA-Clipper lightbar menu system. Before invoking MENU TO, first define the menu items and associated MESSAGEs with a series of @...PROMPT commands. Then, activate the menu with MENU TOidVar. If idVar does not exist or is not visible, MENU TO creates it as a private variable and places the highlight on the first menu item. If idVar does exist, its initial value determines the first menu item highlighted.
Notes
■ Color: Menu items are painted in the current standard color
with the highlighted menu item appearing in the current enhanced color.
■ Navigation and selection: Pressing the arrow keys moves the
highlight to the next or previous menu item. As each menu item is highlighted the associated MESSAGE displays on the row specified with SET MESSAGE. If WRAP is ON, an Up arrow from the first menu item moves the highlight to the last menu item. Also, a Down arrow from the last menu item moves the highlight to the first.
To make a selection, press Return or the first character of a menu item. MENU TO then returns the position of the selected menu item as a numeric value into the specified memory variable. Pressing Esc aborts the menu selection and returns zero. The table below summarizes the active keys within MENU TO.
■ SET KEY procedures: A MENU TO command can be nested within a
SET KEY procedure invoked within a menu without clearing the pending PROMPTs.
MENU TO Active Keys
Key Action
Up arrow Move to previous menu item
Down arrow Move to next menu item
Home Move to first menu item
End Move to last item menu item
Left arrow Move to previous menu item
Right arrow Move to next menu item
PgUp Select menu item, returning position
PgDn Select menu item, returning position
Return Select menu item, returning position
Esc Abort selection, returning zero
First letter Select first menu item with same first letter,
returning position
Examples
■ This example creates a simple vertical lightbar menu with
messages appearing centered on line 23. When invoked, the highlight
defaults to the second menu item based on the initial value of
nChoice:
LOCAL nChoice := 2
SET WRAP ON
SET MESSAGE TO 23 CENTER
@ 6, 10 PROMPT "Add" MESSAGE "New Acct"
@ 7, 10 PROMPT "Edit" MESSAGE "Change Acct"
@ 9, 10 PROMPT "Quit" MESSAGE "Return to DOS"
MENU TO nChoice
//
DO CASE
CASE nChoice = 0
QUIT
CASE nChoice = 1
NewAccount()
CASE nChoice = 2
ChangeAccount()
CASE nChoice = 3
QUIT
ENDCASE
RETURN
MHide() hides the mouse pointer. This function should be used together with MShow() when updating the screen. It is important to hide the mouse pointer before changing the screen display and then show it again after the change.
Note: The MSetCursor() function should be used in place of MShow() and MHide(). It is kept here for compatibility.
Examples
■ This example uses the mouse pointer:
MHide()
@ 10, 20 say "Hi there, folks!!!"
MShow()
■ You can automate calls to MHide()/MShow() by modifying parts
of your header files (*.ch). For example:
#command @ <row>, <col> SAY <xpr>;[PICTURE <pic>];
[COLOR <color>];
=> DevPos(<row>, <col>);
DevOutPict(<xpr>, <pic> [, <color>])
// Can be changed to
#command @ <row>, <col> SAY <xpr>;
[PICTURE <pic>];
[COLOR <color>];
=> MHide();
DevPos(<row>, <col>);
DevOutPict(<xpr>, <pic> [, <color>]);
MShow()
nExp1 and nExp2 are the numeric values to be compared.
dExp1 and dExp2 are the date values to be compared.
Returns
Min() returns the smaller of the two arguments. The value returned is the same data type as the arguments.
Description
Min() is a numeric and date function that ensures the value of an expression is smaller than a specified minimum. The inverse of Min() is Max() which returns the greater of two numeric or date values.
Examples
■ In these examples Min() returns the smaller of two numeric
values:
? Min(99, 100) // Result: 99
? Min(100, 99) // Result: 99
■ In these examples Min() compares date values:
? Date() // Result: 09/01/90
? Min(Date(), Date() + 30) // Result: 09/01/90
cString is the character string or memo field to be counted.
nLineLength specifies the number of characters per line and can range from four to 254. If not specified, the default line length is 79.
nTabSize defines the tab size. If not specified, the default value is four. If nTabSize is greater than or equal to nLineLength, then the tab size is automatically converted to nLineLength - 1.
lWrap toggles word wrap on and off. Specifying true (.T.) toggles word wrap on; false (.F.) toggles it off. If not specified, the default value is true (.T.).
Returns
MLCount() returns the number of lines in cString depending on the nLineLength, the nTabSize, and whether word wrapping is on or off.
Description
MLCount() is a memo function used with MemoLine() to print character strings and memo fields based on the number of characters per line. In the basic operation, use MLCount() to return the number of lines in the character string or memo field. Then, using MemoLine() to extract each line, loop through the memo field until there are no lines left.
If lWrap is true (.T.) and an end of line position breaks a word, it is word wrapped to the next line and the next line begins with that word. If lWrap is false (.F.), MLCount() counts the number of characters specified by nLineLength as the current line. The next line begins with the character following the next hard or soft carriage return. Intervening characters are ignored.
Examples
■ This example displays the contents of each Notes memo field in
the Sales database file, one line at a time:
USE Sales NEW
nLineLength = 65
//
DO WHILE !Eof()
nLines = MLCount(Sales->Notes, nLineLength)
FOR nCurrLine = 1 TO nLines
? MemoLine(Sales->Notes, nLineLength, nCurrLine)
NEXT
SKIP
?
ENDDO
nTabSize is the number of columns between tab stops. If not specified, the default is 4.
lWrap is the word wrap flag. If not specified, the default is
true (.T.).
Returns
MLCToPos() returns the byte position within cText counting from 1.
Description
MLCToPos() is a memo function that determines the byte position that corresponds to a particular line and column within the formatted text. Note that the line number is one-relative and the column number is zero-relative. This is compatible with MemoEdit(). The return value is one-relative, making it suitable for use in SubStr() or other string functions.
MLCToPos() is used with MPosToLC() to create search routines or other text processing for MemoEdit(). Refer to the source code for the program editor (PE.EXE) found in the \CLIP53\SOURCE\PE directory.
Examples
■ This example determines the byte position of line 5, column 3
in the cText string:
cText := "Note the side on which the bread ;
is buttered."
//
? MLCToPos(cText, 5, 3, 0) // Result: 10
Determine the press status of the left mouse button
Syntax
MLeftDown() → lIsPressed
Returns
MLeftDown() returns true (.T.) if the left mouse button is currently pressed; otherwise, it returns false (.F.).
Description
MLeftDown() determines the button press status of the left mouse button. This is particularly useful for mouse-oriented routines when the status of its left button is critical, such as dragging and dropping or floating menu bars.
nLineLength specifies the number of characters per line.
nLine specifies the line number.
nTabSize defines the tab size. The default is four. If nTabSize is greater than or equal to nLineLength, then the tab size is adjusted to nLineLength - 1.
lWrap toggles word wrap on and off. Specifying true (.T.) toggles word wrap on, and false (.F.) toggles it off. The default is true (.T.).
Returns
MLPos() returns the character position of nLine in cString as an integer numeric value. If nLine is greater than the number of lines in cString, MLPos() returns the length of cString.
Examples
■ This example uses MLPos() to find the position of a specific
line, given a line length:
cString = MemoRead("Temp.txt")
nLineLength = 40
nLine = 5
nPosition = MLPos(cString, nLineLength, nLine)
? SubStr(cString, nPosition, 12)
nDividend is the dividend of the division operation.
nDivisor is the divisor of the division operation.
Returns
Mod() returns a number representing the remainder of nDividend divided by nDivisor.
Description
Mod() is a numeric function that emulates the dBASE III PLUS Mod() function. It is implemented using the CA-Clipper modulus operator (%). Note that there are differences between the dBASE III PLUS Mod() function and the CA-Clipper modulus operator which are described in the following table:
Differences Between dBASE III PLUS Mod() Function and the CA-Clipper Modulus Operator
Dividend Divisor Modulus Operator Mod() dBASE III PLUS
Mod() function
3 0 Error Error 3
3 -2 1 -1 -1
-3 2 -1 1 1
-3 0 Error Error -3
-1 3 -1 2 2
-2 3 -2 1 1
2 -3 2 -1 -1
1 -3 1 -2 -2
Mod() is supplied as a compatibility function and therefore not recommended. It is superseded entirely by the modulus operator (%).
Notes
■ Zero divisor in dBASE III PLUS: In dBASE III PLUS, a zero
divisor returns the dividend for every value of the dividend. In CA-Clipper, by contrast, the modulus of any dividend using a zero divisor causes a runtime error.
■ Zero divisor in earlier versions: In versions of CA-Clipper
prior to Summer '87, a modulus operation with a zero divisor returned zero for all dividends. In Summer '87 and later versions, it returns a runtime error.
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/MOD.PRG.
Month() returns an integer numeric value in the range of zero to 12. Specifying a null date (CToD("")) returns zero.
Description
Month() is a date conversion function that is useful when you require a numeric month value during calculations for such things as periodic reports. Month() is a member of a group of functions that return components of a date value as numeric values. The group includes Day() and Year() to return the day and year values as numerics. CMonth() is a related function that allows you to return the name of the month from a date value.
Examples
■ These examples return the month of the system date:
? Date() // Result: 09/01/90
? Month(Date()) // Result: 9
? Month(Date()) + 1 // Result: 10
■ This example demonstrates Month() acting on a null date:
#define NULL_DATE (CToD(""))
? Month(NULL_DATE) // Result: 0
nPos is the byte position within text counting from one (1).
nTabSize is the number of columns between tab stops. If not specified, the default is four (4).
lWrap is the word wrap flag. If not specified, the default is true (.T.).
Returns
MPosToLC() returns an array containing the line and the column values for the specified byte position, nPos.
Description
MPosToLC() is a memo function that determines the formatted line and column corresponding to a particular byte position within cText. Note that the line number returned is one-relative and the column number is zero-relative. This is compatible with MemoEdit(). nPos is one-relative, compatible with At(), RAt(), and other string functions.
MPosToLC(), used with MLCToPos(), can create search routines or other text processing for MemoEdit(). Refer to the source code for the program editor (PE.EXE) found in \CLIP53\SOURCE\PE directory.
Examples
■ This example determines, for the text string shown, the line
and column corresponding to the tenth character of the text, assuming
a formatting width of five columns. A formatting width of five would
cause each of the first three words to be placed on a line by itself.
The tenth character of the text is the "s" in "side". The word
"side" would be at the leftmost column of the third line of the
formatted text, so the return value is {3, 0}.
cText := "Note the side on which the bread ;
is buttered."
//
aLC := MPosToLC(cText, 5, 10) // Result: {3, 0}
MPresent() returns true (.T.) if a mouse is present; otherwise, it returns false (.F.).
Description
MPresent() determines whether a mouse is available or not. For a mouse to be available, it must be physically installed in addition to loading the appropriate mouse device driver.
MRestState() is a function that is used for re-establishing a previously saved mouse state. This includes the mouse's screen position, visibility, and boundaries.
MRightDown() returns true (.T.) if the mouse's right button is currently pressed; otherwise, it returns false (.F.) .
Description
MRightDown() determines the button press status of the right mouse button. This function is provided in the interest of completeness since, on the PC, the right mouse button is typically reserved for single-click oriented activities such as activating a pop-up menu.
MRow() returns the mouse cursor's current screen row position.
Description
MRow() is a function that is used for determining the mouse cursor's screen row position. This is useful when implementing a hit testing routine whose purpose is to determine if the mouse cursor is on pertinent information when the left mouse button is pressed.
nTop defines the uppermost allowable screen row for the mouse cursor or 0 if omitted. This value may range from 0 to the value of nBottom.
nLeft defines the leftmost allowable screen column for the mouse or 0 if omitted. This value may range from 0 to the value of nRight.
nBottom defines the bottommost screen row for the mouse cursor or MaxRow() if omitted. This value may range from the value of nTop to MaxRow().
nRight defines the rightmost allowable screen column for the mouse or MaxCol() if omitted. This value may range from the value of nLeft to MaxCol().
Returns
MSetBounds() always returns NIL.
Description
MSetBounds() is a function that is used for setting the region of the screen that the mouse cursor is restricted to. The default at startup is the entire screen. This setting is automatically maintained by the runtime's mouse subsystem when the screen mode is changed, for example, from the 50-line mode to the 25-line mode.
MSETPOS () is a function that moves the mouse cursor to a new position on the screen. After the mouse cursor is positioned, MRow() and MCol() are updated accordingly. To control the visibility of the mouse cursor, use MSetCursor().
nCoord List contains the coordinates of the inclusion region which is represented as a comma-separated list of four coordinates whose interpretation differs depending on mode. If nMode is LLM_COOR_TEXT, the coordinates look like this: nTop, nLeft, nBottom, nRight. If nMode is LLM_COOR_GRAPH, the coordinates are nX1, nY1, nX2, nY2.
nMode is one of the following two constants:
Coordinate Type Constants
Constant Description
LLM_COOR_TEXT Specifies that the coordinates are given in lines and
columns of text
LLM_COOR_GRAPH Specifies that the coordinates are given in pixels
Returns
MSETCLIP() returns an array of coordinate information. The coordinates of the inclusion area are given in pixels and then in row/col format:
aRegions := {nIncX1, nIncY1, nIncX2, nIncY2,;
nIncR1, nIncC1, nIncR2, nIncC2,; nCoorType}
Description
MSETCLIP() controls mouse pointer movements. It allows you to restrict movement to a region. When an inclusion is defined and the user tries to move the mouse pointer out of the rectangle, it remains stuck at the edge of the area, but is still visible. This mode should be used to restrict the range of user choices for moving or clicking the mouse.
Notes
The inclusion area is initialized to be the entire screen. To eliminate an inclusion region you just pass the value LLM_INCLUDE as the first parameter or pass the four parameters for maximum screen values 0, 0, MaxCol(), MaxRow().
Examples
■ This example shows how the MSETCLIP() function works:
// Define an inclusion region and save the current
// inclusion region in the array aOldInc
aOldInc := MSETCLIP(5, 5, 20, 75,LLM_COOR_TEXT)
// Code for selecting objects and buttons
// Restore old inclusion region
MSETCLIP(aOldInc[5],;
aOldInc[6],;
aOldInc[7],;
aOldInc[8],;
LLG_VIDEO_TEXT)
nStyle defines the style of mouse pointer using one of the constants listed in the table below:
Text and Graph Constants
Constant Description
LLM_COOR_TEXT Specifies that the coordinates are passed in rows and
columns of text
LLM_COOR_GRAPH Specifies that the coordinates are passed in pixels
nCursorShape is a numeric value representing the mouse cursor shape. The following are the possible values predefined for this parameter:
Cursor Shape Constants
Constant Description
LLM_CURSOR_ARROW Standard pointer
LLM_CURSOR_SIZE_NS North South arrow
LLM_CURSOR_SIZE_WE West East arrow
LLM_CURSOR_SIZE_NW_SE North-West South-East arrow
LLM_CURSOR_SIZE_NE_SW North-East South-West arrow
LLM_CURSOR_HAND Hand
LLM_CURSOR_FINGER Hand with one pointing finger
LLM_CURSOR_CROSS Cross
LLM_CURSOR_WAIT Hourglass
Returns
MShow() returns the previously used cursor shape. See nCurorShape above for further information.
Description
MShow() displays the mouse pointer. It is generally used without parameters to simply redisplay the mouse pointer at the position where MHide() hid it (assuming the user has not moved the mouse).
It is possible to use two sets of parameters with this function.
■ Specify the coordinates where the pointer should appear. In
this case, three parameters must be passed: the mode and its coordinates. In text mode, coordinates are passed as row and column. In graphic mode, you can pass either text or graphic coordinates. Conversion is done automatically based on the font size of the current characters.
■ You can also specify the mouse cursor shape to be displayed
when the mouse is visible. This feature is available in graphic mode only.
It is important to hide the mouse pointer before any new screen display, and then show it again. See MHide() for further information on how to do this.
Note: The MSetCursor() function should be used in place of MShow() and MHide(). It is kept here for compatibility.
Examples
■ The following example hides the mouse pointer before using an
@...SAY command and then redisplays it. Next, the mouse pointer is
repositioned, hidden, changed to an hour-glass, and then restored to
its previous shape:
LOCAL nOldShape := 0
MHide()
@ 10, 20 say "Hello world!!!"
MShow()
// Position the pointer at the center of the screen
MShow(MaxCol() / 2, MaxRow() / 2, LLM_COOR_TEXT)
MHide()
@ 10, 20 say "Please wait ..."
// Display an hour glass cursor
nOldShape := MShow(LLM_CURSOR_WAIT)
// Your code
// Restore previously used cursor
MShow(nOldShape)
LLM_STATE_LEFT State of left mouse button. LLM_BUTTON_DOWN
means down and LLM_BUTTON_UP means up.
LLM_STATE_RIGHT State of right mouse button. LLM_BUTTON_DOWN
means down and LLM_BUTTON_UP means up.
LLM_STATE_VISIBLE State of mouse pointer. True (.T) means
visible and false (.F) means invisible. (See
MShow() and MHide() for more information.)
LLM_STATE_DRIVER Indicates version of mouse driver.
LLM_STATE_SHAPE Mouse cursor shape. (See note below.)
LLM_STATE_CLICKS_LEFT Number of left clicks since last MSTATE() call.
LLM_STATE_CLICKS_RIGHT Number of right clicks since last MSTATE()
call.
Note: The following are the possible values predefined for this return array position: LLM_CURSOR_ARROW, LLM_CURSOR_SIZE_NS, LLM_CURSOR_SIZE_WE, LLM_CURSOR_SIZE_NW_SE, LLM_CURSOR_SIZE_NE_SW, LLM_CURSOR_HAND, LLM_CURSOR_FINGER, LLM_CURSOR_CROSS, LLM_CURSOR_WAIT. For a description of these values see the MShow() table of Cursor Shape Constants.
If the mouse is missing, 0 is returned.
The number of clicks (i.e., aState[LLM_STATE_CLICKS_LEFT] and aState[LLM_STATE_CLICKS_RIGHT]) is reset each time MSTATE() is called. Use MSTATE() to reset the mouse settings when needed.
Description
MSTATE() returns information on the mouse state, i.e., the current screen position of the pointer, the state of the left and right mouse buttons, the visibility status of the mouse pointer, and the version of the mouse driver.
Notes
If the version of the mouse driver (i.e., aState[LLM_STATE_DRIVER]) is NULL (""), this indicates that the mouse is not connected or is configured incorrectly. Do not hesitate to insert a version check such as the following:
IFMSTATE()[LLM_STATE_DRIVER]<=500
// Consider the mouse to be absent
ELSE
// Consider the mouse to be present
ENDIF
Warning! Old mouse drivers are usually unreliable and can cause odd behavior in your application, such as a poorly drawn pointer and unsatisfactory saves and restores of the pointer and underlying pixels.
Examples
■ This example shows how to use MSTATE() function:
// Show the mouse pointer
MShow()
DO WHILE Inkey() != K_ESC
// Retrieve mouse state
aState := MSTATE()
// Line position
@ 24, 0 SAY aState[LLM_STATE_ROW]
// Column position
@ 24, 10 SAY aState[LLM_STATE_COL]
// State of left button
@ 24, 20 SAY "Left" + If(aState[LLM_STATE_LEFT]==LLM_BUTTON_DOWN,;
"Down" ,;
"Up")
// State of right button
@ 24, 40 SAY "Right " + If(aState[LLM_STATE_RIGHT]== ;
LLM_BUTTON_DOWN ,;
"Down" ,;
"Up")
ENDDO
// Hide the mouse pointer
MHide()
lNewError, if specified, sets the value returned by NetErr() to the specified status. lNewError can be either true (.T.) or false (.F.). Setting NetErr() to a specified value allows the runtime error handler to control the way certain file errors are handled. For more information, refer to Errorsys.prg.
Returns
NetErr() returns true (.T.) if a USE or APPEND BLANK fails. The initial value of NetErr() is false (.F.). If the current process is not running under a network operating system, NetErr() always returns false (.F.).
Description
NetErr() is a network function. It is a global flag set by USE, USE...EXCLUSIVE, and APPEND BLANK in a network environment. It is used to test whether any of these commands have failed by returning true (.T.) in the following situations:
NetErr() Causes
Command Cause
USE USE EXCLUSIVE by another process
USE...EXCLUSIVE USE EXCLUSIVE or USE by another process
APPEND BLANK FLock() or RLock() of LastRec() + 1 by another user
NetErr() is generally applied in a program by testing it following a USE or APPEND BLANK command. If it returns false (.F.), you can perform the next operation. If the command is USE, you can open index files. If it is APPEND BLANK, you can assign values to the new record with a REPLACE or @...GET command. Otherwise, you must handle the error by either retrying the USE or APPEND BLANK, or terminating the current operation with a BREAK or RETURN.
Examples
■ This example demonstrates typical usage of NetErr(). If the
USE succeeds, the index files are opened and processing continues.
If the USE fails, a message displays and control returns to the
nearest BEGIN SEQUENCE construct:
USE Customer SHARED NEW
IF !NetErr()
SET INDEX TO CustNum, CustOrders, CustZip
ELSE
? "File is in use by another"
BREAK
ENDIF
NetName() returns the workstation identification as a character string up to 15 characters in length. If the workstation identification was never set or the application is not operating under the IBM PC Network, it returns a null string ("").
Examples
■ This example demonstrates the NetName() result when a
workstation is started as a network node with a station identifier of
"STATION 1":
? NetName() // Result: STATION 1
■ This example demonstrates the NetName() result when a
workstation is started as a stand-alone unit:
? NetName() // Result: ""
NextKey() returns an integer numeric value ranging from -39 to 386 for keyboard events and integer values from 1001 to 1007 for mouse events. This value identifies either the key extracted from the keyboard buffer or the mouse event that last occurred. If the keyboard buffer is empty and no mouse events are taking place, NextKey() returns zero. If SET TYPEAHEAD is zero, NextKey() always returns zero.
Description
NextKey() is a function that reads the keystroke pending in the keyboard buffer or the next mouse event without removing it. The value returned is the Inkey() code of the key pressed—the same value as returned by Inkey() and LastKey(). NextKey() returns values for all ASCII characters as well as function, Alt+function, Ctrl+function, Alt+letter, and Ctrl+letter key combinations.
NextKey() is like the Inkey() function but differs in one fundamental respect. Inkey() removes the pending key from the keyboard buffer and updates LastKey() with the value of the key. by contrast NextKey() reads, but does not remove the key from the keyboard buffer, and does not update LastKey().
Since NextKey() does not remove the key from the keyboard buffer, it can be used to poll the keyboard, and then pass control to a routine that uses a wait state or Inkey() to actually fetch the key from the buffer.
For a complete list of Inkey() codes and inkey.ch constants, refer to the "CA-Clipper Inkey Codes Appendix" in the Error Messages and Appendices Guide.
Examples
■ This example places an Esc key in the keyboard buffer, and
then shows the differences between Inkey(), LastKey(), and NextKey():
#include "Inkey.ch"
//
CLEAR TYPEAHEAD
KEYBOARD CHR(K_ESC)
//
? NextKey(), LastKey() // Result: 27 0
? Inkey(), LastKey() // Result: 27 27
? NextKey() // Result: 0
lToggle is a logical value that toggles the current state of snow suppression. A value of true (.T.) enables the snow suppression on, while a value of false (.F.) disables snow suppression.
Description
NoSnow() is used to suppress snow on CGA monitors. Typically, use NoSnow() in the configuration section of your application to give the user the option to suppress snow.
commentText is a string of characters placed after the comment indicator.
Description
NOTE is command synonym for the single-line comment indicator (*). All characters after NOTE are ignored until the CA-Clipper compiler encounters an end of line (carriage return/line feed). This means a single-line comment cannot be continued with the semicolon (;) onto a new line.
If you need a multi-line or inline comment, begin the comment block with a slash-asterisk (/*) symbol and end the comment block with an asterisk-slash (*/) symbol. If you need to comment out a block of code, use the conditional compilation directives #ifdef...#endif instead of multiline comments. This is important since nested comments are illegal.
NOTE is a compatibility command and therefore not recommended. It is superseded by the C-style comment symbols slash-asterisk (/*) and asterisk-slash (*/), as well as the double-slash (//). It is also superseded by the dBASE-style comment symbols, asterisk (*) and the double-ampersand (&&).
For a complete discussion on comment indicators, refer to the "Basic Concepts" chapter in the Programming and Utilities Guide.
Examples
■ These examples show the various comment symbols supported by
CA-Clipper:
// This is a comment
/* This is a comment */
* This is a comment
&& This is a comment
NOTE This is a comment
ordBagExt() is an order management function that returns a character expression that is the default order bag extension of the current or aliased work area. cBagExt is determined by the RDD active in the current work area.
Notes
■ ordBagExt() supersedes the IndexExt() function, which is not
recommended.
■ ordBagExt() returns the default index extension of the driver
loaded, not the actual index file extension.
Examples
USE sample VIA "DBFNTX"
? ordBagExt() // Returns .ntx
nOrder is an integer that identifies the position in the order list of the target order whose order bag name is sought.
cOrderName is a character string that represents the name of the target order whose order bag name is sought.
Returns
ordBagName() returns a character string, the order bag name of the specific order.
Description
ordBagName() is an order management function that lets you access the name of the order bag in which cOrderName resides. You may identify the order as a character string or with an integer that represents its position in the order list. In case of duplicate names, ordBagName() only recognizes the first matching name.
Note: ordBagName(0) works as ordBagName(IndexOrd())
Examples
■ The following example uses ordBagName() with the default
DBFNTX driver:
USE Customer VIA "DBFNTX" NEW
SET INDEX TO CuAcct, CuName, CuZip
ordBagName(2) // Returns: CuName
ordBagName(1) // Returns: CuAcct
ordBagName(3) // Returns: CuZip
■ In this example, Customer.cdx contains three orders named
CuAcct, CuName, CuZip:
USE Customer VIA "DBFCDX" NEW
SET INDEX TO Customer
ordBagName("CuAcct") // Returns: Customer
ordBagName("CuName") // Returns: Customer
ordBagName("CuZip") // Returns: Customer
cForCondition is a string that specifies the FOR condition for the order. This string is returned by dbOrderInfo(DBOI_CONDITION, [cIndexFile], cOrder). If you do not need this information, you can specify a null string ("").
bForCondition is a code block that defines a FOR condition that each record within the scope must meet in order to be processed. If a record does not meet the specified condition, it is ignored and the next record is processed. Duplicate key values are not added to the index file when a FOR condition is used. The default is NIL.
This condition (not cForCondition) is the one that is actually used to create the order. Unlike the WHILE condition and other scoping information, the FOR condition is stored as part of the index file and is used when updating or rebuilding the order with dbReindex(). Any limitations on the FOR condition are determined by the RDD (see the "Replaceable Database Driver Architecture" chapter in the Drivers Guide for information about RDD limitations).
lAll is specified as true (.T.) to define a scope of all records. Use false (.F.) if you want to indicate other record scoping conditions (i.e., nNext, nRecord, or lRest). The default is false (.F.).
bWhileCondition is a code block that defines a condition that each record must meet in order to be processed. If no scope is specified, using a bWhileCondition changes the default scope to lRest. As soon as a record is encountered that causes the condition to fail, the operation terminates.
The WHILE condition is used only to create the order. It is not stored in the index file or used for updating or reindexing purposes. The default is NIL.
bEval is a code block that is evaluated at intervals specified by nInterval. This is useful in producing a status bar or odometer that monitors the ordering progress. The return value of bEval must be a logical value. If bEval returns false (.F.), indexing halts. The default is NIL.
nInterval is a numeric expression that determines the number of times bEval is evaluated. This argument offers a performance enhancement by evaluating the condition at intervals instead of evaluating every record processed. To step through every record, you can specify a value of 0. The default is 0.
nStart is the starting record number. To start at the beginning of the file, specify a value of 0. The default is 0.
You define the scope using one of these three, mutually exclusive arguments (use 0 or false (.F.) for the others). The default is all records. Record scoping information is used only to create the order. It is not stored in the index file or used for index updates and reindexing purposes.
nNext is the number of records to process, starting at nStart. Specify 0 to ignore this argument.
nRecord is a single record number to process. Specify 0 to ignore this argument.
lRest is specified as true (.T.) to process only records from nStart to the end of the file. False (.F.) processes all records.
lDescend specifies whether the keyed pairs should be sorted in decreasing or increasing order of value. True`.T.) results in descending order and false (.F.) results in ascending order. The default is false (.F.).
lAdditive specifies whether open orders should remain open while the new order is being created. True (.T.) specifies that they should remain open. False (.F.) is the default and it specifies that all open orders should be closed.
lCurrent specifies whether only records in the controlling order— and within the current range as specified by ORDSETSCOPE()—will be included in this order. True (.T.) specifies that the controlling order and range should be used to limit the scope of the newly created order. False (.F.) is the default and it specifies that all records in the database file are included in the order.
lCustom specifies whether the new order will be a custom built order (for RDDs that use this feature). True (.T.) specifies that a custom built order will be created. A custom built order is initially empty, giving you complete control over order maintenance. The system does not automatically add and delete keys from a custom built order. Instead, you explicitly add and delete keys using ordKeyAdd() and ordKeyDel(). False (.F.) specifies a standard, system-maintained order. The default is false (.F.).
lNoOptimize specifies whether the FOR condition will be optimized (for RDDs that support this feature). True (.T.) optimizes the FOR condition, and false (.F.) does not. The default is false (.F.).
Returns
ordCondSet() returns true (.T.) if successful; otherwise, it returns false (.F.).
Description
By default ordCondSet() operates on the currently selected work area. This function can be made to operate on an unselected work area by specifying it within an aliased expression.
Unless you specify otherwise with ordCondSet(), new orders that you create will use default scoping rules, processing all records in the work area. ordCondSet() allows you to specify conditions and scoping rules that records must meet in order to be included in the next order created. Creating a new order automatically resets the work area to use the default scoping rules. Thus, if scoping is required, you must reset ordCondSet() each time you create a new order.
This function is essential if you want to create conditional orders using dbCreateIndex() because this function does not support arguments to do this.
Examples
■ The following example sets the condition for the creation of
orders:
LOCAL cFor AS STRING
LOCAL lAll, lRest, lDescend AS LOGIC
LOCAL bForCondition, bWhileCondition, ;
bEval AS USUAL
LOCAL nStep, nStart, nNext, nRecord AS SHORTINT
// For condition string format
cFor := 'Upper(Name) = "MELISSA"'
// Actual for condition
bForCondition := {|| Upper(Name) = "MELISSA"}
lAll := .T.
bWhileCondition := {|| .T.} // While all
bEval := {|| Name + City} // Indexing code
// block
nStep := 0 // Step through all
nStart := 0 // From top
nNext := 0 // All
nRecord := 0 // All records
lRest := .F. // All
lDescend := .F. // Ascending
ordCondSet(cFor, bForCondition, lAll, ;
bWhileCondition, bEval, nStep, nStart, ;
nNext, nRecord, lRest, lDescend)
cOrderBagName is the name of a disk file containing one or more orders. You may specify cOrderBagName as the file name with or without the path name or extension. Without the extension, CA-Clipper uses the default extension of the current RDD.
cOrderName is the name of the order to be created.
Note: Although both cOrderBagName and cOrderName are both optional, at least one of them must be specified.
cExpKey is an expression that returns the key value to place in the order for each record in the current work area. cExpKey can represent a character, date, logical, or numeric data type. The database driver determines the maximum length of the index key expression.
bExpKey is a code block that evaluates to a key value that is placed in the order for each record in the current work area. If you do not supply bExpKey, it is macro-compiled from cExpKey.
lUnique is an optional logical value that specifies whether a unique order is to be created. If lUnique is omitted, the current global _SET_UNIQUE setting is used.
Returns
ordCreate() always returns NIL.
Description
ordCreate() is an order management function that creates an order in the current work area. It works like dbCreateIndex() except that it lets you create orders in RDDs that recognize multiple-order bags. ordCreate() supersedes the dbCreateIndex() function because of this capability, and it is the preferred function.
The active RDD determines the order capacity of an order bag. The default DBFNTX and DBFNDX drivers only support single-order bags, while other RDDs may support multiple-order bags (e.g., the DBFCDX and DBFMDX drivers).
In RDDs that support production or structural indices (e.g., DBFCDX, DBPX), if you specify a tag but do not specify an order bag, the tag is created and added to the index. If no production or structural index exists, it will be created and the tag will be added to it. When using RDDs that support multiple-order bags, you must explicitly SET ORDER (or ordSetFocus()) to the desired controlling order. If you do not specify a controlling order, the data file will be viewed in natural order.
If cOrderBagName does not exist, it is created in accordance with the RDD in the current or specified work area.
If cOrderBagName exists and the RDD specifies that order bags can only contain a single order, cOrderBagName is erased and the new order is added to the order list in the current or specified work area.
If cOrderBagName exists and the RDD specifies that order bags can contain multiple tags, cOrderName is created if it does not already exist; otherwise cOrderName is replaced in cOrderBagName and the order is added to the order list in the current or specified work area.
Examples
■ The following example demonstrates ordCreate() with the DBFNDX
driver:
USE Customer VIA "DBFNDX" NEW
ordCreate("CuAcct",, "Customer->Acct")
■ The following example demonstrates ordCreate() with the
default DBFNTX driver:
USE Customer VIA "DBFNTX" NEW
ordCreate("CuAcct", "CuAcct", "Customer->Acct", ;
{|| Customer->Acct })
■ The following example demonstrates ordCreate() with the FoxPro
driver, DBFCDX:
USE Customer VIA "DBFCDX" NEW
ordCreate("Customer", "CuAcct", "Customer->Acct")
■ This example creates the order "CuAcct" and adds it to the
production index (order bag) "Customer." The production index will
be created if it does not exist:
USE Customer VIA "DBFMDX" NEW
ordCreate(, "CuAcct", "Customer->Acct")
cOrder | nPosition is the name of the order or a number representing its position in the order list. Using the order name is the preferred method since the position may be difficult to determine using multiple-order index files. If omitted or NIL, the controlling order is assumed.
Specifying an invalid value will raise a runtime error.
cIndexFile is the name of an index file, including an optional drive and directory (no extension should be specified). Use this argument with cOrder to remove ambiguity when there are two or more orders with the same name in different index files.
If cIndexFile is not open by the current process, a runtime error is raised.
lNewDescend is a logical value that if true (.T.) dynamically turns on the descending flag for the order, resulting in descending order. False (.F.) dynamically turns the flag off, resulting in ascending order.
Returns
If lNewDescend is not specified, ordDescend() returns the current setting. If lNewDescend is specified, the previous setting is returned.
Description
ordDescend() changes the ascending/descending flag at runtime only—it does not change the descending flag stored in the actual index file. To change the descending flag in the index file, see the INDEX command in the Reference Guide, Volume 1.
By default, this function operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression.
Examples
■ The following example illustrates ordDescend(). Every order
can be both ascending and descending:
USE Customer VIA "DBFCDX"
INDEX ON LastName TAG Last
INDEX ON FirstName TAG First DESCENDING
SET ORDER TO TAG Last
// Last was originally created in ascending order
// Swap it to descending
ordDescend(,, .T.)
// Last will now be processed in descending order
SET ORDER TO TAG First
// First was originally created in descending order
// Swap it to ascending
ordDescend(,, .F.)
// First will now be processed in ascending order
cOrderName is the name of the order to be removed from the current or specified work area.
cOrderBagName is the name of a disk file containing one or more orders. You may specify cOrderBagName as the file name with or without the path name or appropriate extension. If you do not include the extension as part of cOrderBagName, CA-Clipper uses the default extension of the current RDD.
Returns
ordDestroy() always returns NIL.
Description
ordDestroy() is an order management function that removes a specified order from multiple-order bags.
The active RDD determines the order capacity of an order bag. The default DBFNTX and the DBFNDX drivers only support single-order bags, while other RDDs may support multiple-order bags (e.g., the DBFCDX and DBPX drivers).
Note: RDD suppliers may define specific behaviors for this command.
Warning! ordDestroy() is not supported for DBFNDX and DBFNTX.
Examples
■ This example demonstrates ordDestroy() with the FoxPro driver,
DBFCDX:
USE Customer VIA "DBFCDX" NEW
SET INDEX TO Customer, CustTemp
ordDestroy("CuAcct", "Customer")
cOrderName is the name of the target order whose cForExp is sought.
nOrder is an integer that identifies the position in the order list of the target order whose cForExp is sought.
cOrderBagName is the name of an order bag containing one or more orders. You may specify cOrderBagName as the file name with or without the path name or appropriate extension. If you do not include the extension as part of cOrderBagName, CA-Clipper uses the default extension of the current RDD.
Returns
ordFor() returns a character expression, cForExp, that represents the FOR condition of the specified order. If the order was not created using the FOR clause, the return value will be an empty string (""). If the database driver does not support the FOR condition, it may either return an empty string ("") or raise an "unsupported function" error, depending on the driver.
Description
ordFor() is an order management function that returns the character string, cForExp, that represents the logical FOR condition of cOrderName or nOrder.
■ This example retrieves the FOR condition from an order:
USE Customer NEW
INDEX ON Customer->Acct ;
TO Customer ;
FOR Customer->Acct > "AZZZZZ"
ordFor("Customer") // Returns: Customer->Acct > "AZZZZZ"
cOrder | nPosition is the name of the order or a number representing its position in the order list. Using the order name is the preferred method since the position may be difficult to determine using multiple-order index files. If omitted or NIL, the controlling order is assumed.
Specifying an invalid order will raise a runtime error.
cIndexFile is the name of an index file, including an optional drive and directory (no extension should be specified). Use this argument with cOrder to remove ambiguity when there are two or more orders with the same name in different index files.
If cIndexFile is not open by the current process, a runtime error is raised.
Returns
ordIsUnique() returns the status of the indicated order's unique flag as a logical value.
Description
By default, this function operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression.
Examples
■ This example shows the return value of ordIsUnique() using
various orders:
USE Customer VIA "DBFCDX"
INDEX ON LastName TAG Last UNIQUE
INDEX ON FirstName TAG First
INDEX ON Age TO j:\test\tmp\age UNIQUE
SET ORDER TO TAG Last
? ordIsUnique() // Result: .T. for Last
? ordIsUnique("First") // Result: .F.
? ordIsUnique("Age") // Result: .T.
cOrderName is the name of an order, a logical ordering of a database.
nOrder is an integer that identifies the position in the order list of the target order whose cExpKey is sought.
cOrderBagName is the name of a disk file containing one or more orders. You may specify cOrderBagName as the file name with or without the path name or appropriate extension. If you do not include the extension as part of cOrderBagName, CA-Clipper uses the default extension of the current RDD.
Returns
Returns a character string, cExpKey.
Description
ordKey() is an order management function that returns a character expression, cExpKey, that represents the key expression of the specified order.
You may specify the order by name or with a number that represents its position in the order list. Using the order name is the preferred method.
The active RDD determines the order capacity of an order bag. The default DBFNTX and the DBFNDX drivers only support single-order bags, while other RDDs may support multiple-order bags (e.g., the DBFCDX and DBFMDX drivers).
■ This example retrieves the index expression from an order:
USE Customer NEW
INDEX ON Customer->Acct ;
TO Customer ;
FOR Customer->Acct > "AZZZZZ"
ordKey("Customer") // Returns: Customer->Acct
cOrder | nPosition is the name of the order or a number representing its position in the order list. Using the order name is the preferred method since the position may be difficult to determine using multiple-order index files. If omitted or NIL, the controlling order is assumed.
Specifying an invalid order, such as one that is not custom built, will raise a runtime error.
cIndexFile is the name of an index file, including an optional drive and directory (no extension should be specified). Use this argument with cOrder to remove ambiguity when there are two or more orders with the same name in different index files.
If cIndexFile is not open by the current process, a runtime error is raised.
expKeyValue is a specific key value that you want to add for the current record. The data type must match that of the order. If not specified, the order's key expression is evaluated for the current record and added to the order.
Returns
ordKeyAdd() returns true (.T.) if successful; otherwise, it returns false (.F.).
Description
ordKeyAdd() adds keys to a custom built order which is an order that is not automatically maintained by the DBFCDX driver. You can determine if an order is custom built using dbOrderInfo(DBOI_CUSTOM, ...). When you create such an order, it is initially empty. You must then manually add and delete keys using ordKeyAdd() and ordKeyDel().
Note: An existing order can be changed to a custom built order by using the dbOrderInfo() function.
ordKeyAdd() evaluates the key expression (or expKeyValue, if specified), and then adds the key for the current record to the order. If the order has a for condition, the key will be added only if that condition is met, and then only if it falls within the current scoping range.
Note: You can add several keys for the same record with consecutive calls to ordKeyAdd().
ordKeyAdd() will fail if:
■ The record pointer is positioned on an invalid record (i.e.,
■ No order was specified and there is no controlling order
By default, this function operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression.
Examples
■ This example creates a custom index and adds every fiftieth
record to it:
USE Customer VIA "DBFCDX"
// Create custom-built order that is initially empty
INDEX ON LastName TO Last CUSTOM
// Add every 50th record
FOR n := 1 TO RecCount() STEP 50
GOTO n
ordKeyAdd()
NEXT
cOrder | nPosition is the name of the order or a number representing its position in the order list. Using the order name is the preferred method since the position may be difficult to determine using multiple-order index files. If omitted or NIL, the controlling order is assumed.
Specifying an invalid order will raise a runtime error.
cIndexFile is the name of an index file, including an optional drive and directory (no extension should be specified). Use this argument with cOrder to remove ambiguity when there are two or more orders with the same name in different index files.
If cIndexFile is not open by the current process, a runtime error is raised.
Returns
ordKeyCount() returns the number of keys in the specified order.
Description
ordKeyCount() counts the keys in the specified order and returns the result as a numeric value. If the order is not conditional and no scope has been set for it, ordKeyCount() is identical to RecCount(), returning the number of records in the database file. However, for a conditional order, there may be fewer keys than there are records, since some records may not meet the order's for condition or may not fall inside the scope specified by ordScope()—in counting the keys, ordKeyCount() respects the currently defined scope and for condition.
By default, this function operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression.
Examples
■ This example demonstrates using ordKeyCount() with various
orders:
USE customer
// Assume 1000 total records,
// 500 less than thirty years old, and
// 895 making less than 50,000
INDEX ON Age TO Age
INDEX ON First TO First FOR Age < 30
INDEX ON Last TO Last FOR Salary < 50000
// Age is the controlling order
SET INDEX TO Age, First, Last
? RecCount() // Result: 1000
? ordKeyCount() // Result: 1000
? ordKeyCount("First") // Result: 500
? ordKeyCount(3) // Result: 895
cOrder | nPosition is the name of the order or a number representing its position in the order list. Using the order name is the preferred method since the position may be difficult to determine using multiple-order index files. If omitted or NIL, the controlling order is assumed.
Specifying an invalid order, such as one that is not custom built, will raise a runtime error.
cIndexFile is the name of an index file, including an optional drive and directory (no extension should be specified). Use this argument with cOrder to remove ambiguity when there are two or more orders with the same name in different index files.
If cIndexFile is not open by the current process, a runtime error is raised.
expKeyValue is a specific key value that you want to delete for the current record. The data type must match that of the order. If not specified, the order's key expression is evaluated for the current record and deleted from the order.
Returns
ordKeyDel() returns true (.T.) if successful; otherwise, it returns false (.F.).
Description
ordKeyDel() deletes a key from a custom built order which is an order that is not automatically maintained by the DBFCDX driver. You can determine if an order is custom built using dbOrderInfo(DBOI_CUSTOM, ...). When you create such an order, it is initially empty. You must then manually add and delete keys using ordKeyAdd() and ordKeyDel().
Note: An existing order can be changed to a custom built order by using the dbOrderInfo() function.
ordKeyDel() evaluates the key expression (or expKeyValue, if specified), and then deletes the key for the current record from the order.
ordKeyDel() will fail if:
■ The record pointer is positioned on an invalid record (for
example, Eof() returns true (.T.) or the record pointer is positioned on a record that falls outside the order's scope or for condition)
■ The specified order is not custom built
■ The specified order does not exist
■ No order was specified and there is no controlling order
By default, this function operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression.
Examples
■ This example creates a custom index, adds every fiftieth
record to it, and deletes every hundredth record:
USE Customer VIA "DBFCDX"
// Create custom-built order that is initially empty
INDEX ON LastName TO Last CUSTOM
// Add every 50th record
FOR n := 1 TO RecCount() STEP 50
GOTO n
ordKeyAdd()
NEXT
// Remove every 100th record
FOR n := 1 TO RecCount() STEP 100
GOTO n
ordKeyDel()
NEXT
Move to a record specified by its logical record number in the controlling order
Syntax
ordKeyGoto(<nKeyNo>) → lSuccess
Arguments
nKeyNo is the logical record number. If the value specified does not satisfy the scope or for condition for the order, the record pointer is positioned at the end of file.
Returns
ordKeyGoto() returns true (.T.) if successful; otherwise, it returns false (.F.).
Description
ordKeyGoto() is the complement to ordKeyNo(). ordKeyNo() returns the logical record number (i.e., its position in the controlling order) of the current record, and ordKeyGoto() moves the record pointer to the specified logical record.
Tip: This function can be useful when displaying scroll bars. If the user clicks on a certain position on the scroll bar, you can move to the corresponding record by calling ordKeyGoto().
By default, this function operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression.
Examples
■ This example shows the difference between physical and logical
record number:
USE Customer
SET INDEX TO First // Make records in first name
// order
ordKeyGoto(100) // Go to the 100th logical record
? RecNo() // Returns the physical record
// number
? ordKeyNo() // Returns 100, the logical
// record no
cOrder | nPosition is the name of the order or a number representing its position in the order list. Using the order name is the preferred method since the position may be difficult to determine using multiple-order index files. If omitted or NIL, the controlling order is assumed.
Specifying an invalid order will raise a runtime error.
cIndexFile is the name of an index file, including an optional drive and directory (no extension should be specified). Use this argument with cOrder to remove ambiguity when there are two or more orders with the same name in different index files.
If cIndexFile is not open by the current process, a runtime error is raised.
Returns
ordKeyNo() returns the relative position of the current record in the specified order as a numeric value. ordKeyNo() respects the scope and for condition of the order by returning zero if the record pointer is positioned on an invalid record or if Eof() is true (.T.).
Description
ordKeyNo() returns the logical record number of a key in an order. This is in contrast to the physical record number (returned using the RecNo() function), which is the relative position of the record in the physical database file.
Tip: This function can be useful for displaying scroll bars and messages, such as "Record 9 of 123," when viewing records in a browser.
By default, this function operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression.
Examples
■ This example shows the difference between physical and logical
record number:
USE Customer // Assuming 1000 records
SET INDEX TO First // Make records in first order
GO TOP // Position the data pointer at
// the first record
? ordKeyNo() // Result: 1
dbSkip(10)
? ordKeyNo() // Result: 11
? RecNo() // Result: Physical record number
dbGoBottom()
? ordKeyNo() // Result: 1000
? RecNo() // Result: Physical record number
Get the key value of the current record from the controlling order
Syntax
ordKeyVal() → uKeyValue
Returns
ordKeyVal() returns the current record's key value. The data type of the return value is the same as that of the key expression used to create the order. Use ValType() to determine the data type.
ordKeyVal() returns NIL if:
■ There is no controlling order
■ The record pointer is at the end of file (Eof() returns true
(.T.))
■ There is no key defined for this record (for example, you have
positioned the record pointer to a record that does not meet the order's for condition or that lies outside of its specified scope)
Description
The key value is retrieved from the controlling order, not the database file. This makes the retrieval faster because no time is spent reading in the actual record.
Tip: ordKeyVal() is fast, but if you are going to use the value more than once, it is faster to store the result in a local variable. Then use the local variable rather than calling ordKeyVal() repeatedly for the same record.
By default, this function operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression.
Examples
■ This example displays the values for all keys in an order
without ever reading the individual records into memory:
FUNCTION DISPLAYKEYS()
LOCAL cKey, cFirst, cLast
USE Customer
// Assuming both LastName and FirstName are
// 20 characters
INDEX ON LastName + FirstName TO LastFir
DO WHILE !Customer->Eof()
cKey := Customer->ordKeyVal() // Get key
// value
cLast := Left(cKey, 20) // Get last
// name
cFirst := Right(cKey, 20) // Get first
// name
? cLast, cFirst
Customer->dbSkip()
ENDDO
CLOSE
cOrderBagName is the name of a disk file containing one or more orders. You may specify cOrderBagName as the file name with or without the path name or appropriate extension. If you do not include the extension as part of cOrderBagName, CA-Clipper uses the default extension of the current RDD.
cOrderName the name of the specific order from the order bag to be added to the order list of the current work area. If you do not specify cOrderName, all orders in the order bag are added to the order list of the current work area.
Returns
ordListAdd() always returns NIL.
Description
ordListAdd() is an order management function that adds the contents of an order bag, or a single order in an order bag, to the order list. This function lets you extend the order list without issuing a SET INDEX command that, first, clears all the active orders from the order list.
Any orders already associated with the work area continue to be active. If the newly opened order bag contains the only order associated with the work area, it becomes the controlling order; otherwise, the controlling order remains unchanged.
After the new orders are opened, the work area is positioned to the first logical record in the controlling order.
ordListAdd() is similar to the SET INDEX command or the INDEX clause of the USE command, except that it does not clear the order list prior to adding the new order(s).
ordListAdd() supersedes the dbSetIndex() function.
The active RDD determines the order capacity of an order bag. The default DBFNTX and the DBFNDX drivers only support single-order bags, while other RDDs may support multiple-order bags (e.g., the DBFCDX driver). When using RDDs that support multiple-order bags, you must explicitly SET ORDER (or ordSetFocus()) to the desired controlling order. If you do not specify a controlling order, the data file will be viewed in first order.
Examples
■ In this example Customer.cdx contains three orders, CuAcct,
CuName, and CuZip. ordListAdd() opens Customer.cdx but only uses the
order named CuAcct:
USE Customer VIA "DBFCDX" NEW
ordListAdd("Customer", "CuAcct")
ordListClear() is an order management function that removes all orders from the order list for the current or aliased work area. When you are done, the order list is empty.
nOrder is an integer that identifies the position in the order list of the target order whose database name is sought.
cOrderBagName is the name of a disk file containing one or more orders. You may specify cOrderBagName as the file name with or without the path name or appropriate extension. If you do not include the extension as part of xcOrderBagName, CA-Clipper uses the default extension of the current RDD.
Returns
ordName() returns the name of the specified order in the current order list or the specified order bag if opened in the current order list.
Description
ordName() is an order management function that returns the name of the specified order in the current order list.
If cOrderBagName is an order bag that has been emptied into the current order list, only those orders in the order list that correspond to cOrderBagName order bag are searched.
The active RDD determines the order capacity of an order bag. The default DBFNTX and the DBFNDX drivers only support single-order bags, while other RDDs may support multiple-order bags (e.g., the DBFCDX and DBPX drivers).
■ This example retrieves the name of an order using its position
in the order list:
USE Customer NEW
SET INDEX TO CuAcct, CuName, CuZip
ordName(2) // Returns: CuName
■ This example retrieves the name of an order given its position
within a specific order bag in the order list:
USE Customer NEW
SET INDEX TO Temp, Customer
// Assume Customer contains CuAcct, CuName, CuZip
ordName(2, "Customer") // Returns: CuName
cOrderName the name of the specific order whose position in the order list is sought.
cOrderBagName is the name of a disk file containing one or more orders. You may specify cOrderBagName as the file name with or without the path name or appropriate extension. If you do not include the extension as part of cOrderBagName, CA-Clipper uses the default extension of the current RDD.
Returns
ordNumber() returns an integer that represents the position of the specified order in the order list.
Description
ordNumber() is an order management function that lets you determine the position in the current order list of the specified order. ordNumber() searches the order list in the current work area and returns the position of the first order that matches cOrderName. If cOrderBagName is the name of an order bag newly emptied into the current order list, only those orders in the order list that have been emptied from cOrderBagName are searched.
If cOrderName is not found, ordNumber() raises a recoverable runtime error.
The active RDD determines the order capacity of an order bag. The default DBFNTX driver only supports single-order bags, while other RDDs may support multiple-order bags (e.g., the DBFCDX and DBPX drivers).
Examples
USE Customer VIA "DBFNTX" NEW
SET INDEX TO CuAcct, CuName, CuZip
ordNumber("CuName") // Returns: 2
nScope is a number specifying the top (TOPSCOPE) or bottom (BOTTOMSCOPE) boundary.
Note: To use the TOPSCOPE and BOTTOMSCOPE constants, you must include (#include) the ord.ch header file in your application.
expNewValue is the top or bottom range of key values that will be included in the controlling order's current scope. expNewValue can be an expression that matches the data type of the key expression in the controlling order or a code block that returns the correct data type.
Omitting expNewValue or specifying it as NIL has the special effect of resetting the specified scope to its original default. The default top range is the first logical record in the controlling order, and the default bottom range is the last logical record.
Returns
If expNewValue is not specified, ordScope() returns and clears the current setting. If expNewValue is specified, the function sets it and the previous setting is returned.
Description
The range of values specified using ordScope() is inclusive. In other words, the keys included in the scope will be greater than or equal to the top boundary and less than or equal to the bottom boundary.
Note: To return current settings without changing them, call the dbOrderInfo() function using the DBOI_SCOPETOP and DBOI_SCOPEBOTTOM constants.
Examples
■ This example illustrates using ordScope() to set various
scoping limitations on an order:
USE Friends
SET INDEX TO Age
// Make 25 the lowest age in range
ordScope(TOPSCOPE, 25)
// Make 30 the highest age in range
ordScope(BOTTOMSCOPE, 30)
LIST Age // Shows records with
// 25 <= Age <= 30
// Change highest age to 35
ordScope(BOTTOMSCOPE, 35)
LIST Age // Shows records with
// 25 <= Age <= 35
// Reset top boundary
ordScope(TOPSCOPE, NIL)
LIST Age // Shows records with
// Age <= 35
// Reset bottom boundary
ordScope(BOTTOMSCOPE, NIL)
LIST Age // Shows all records
cOrderName is the name of the selected order, a logical ordering of a database. ordSetFocus() ignores any invalid values of cOrderName.
nOrder is a number representing the position in the order list of the selected order.
cOrderBagName is the name of a disk file containing one or more orders. You may specify cOrderBagName as the file name with or without the path name or appropriate extension. If you do not include the extension as part of cOrderBagName, CA-Clipper uses the default extension of the current RDD.
Returns
ordSetFocus() returns the order name of the previous controlling order.
Description
ordSetFocus() is an order management function that returns the order name of the previous controlling order and, optionally, sets the focus to an new order.
If you do not specify cOrderName or nOrder, the name of the currently controlling order is returned and the controlling order remains unchanged.
All orders in an order list are properly updated no matter what cOrderName is the controlling order. After a change of controlling orders, the record pointer still points to the same record.
The active RDD determines the order capacity of an order bag. The default DBFNTX driver only supports single-order bags, while other RDDs may support multiple-order bags (e.g., the DBFCDX and DBPX drivers).
bKey is a code block that expresses the relational expression in executable form.
cKey is an optional string value that expresses the relational expression in textual form. If cKey is supplied, it must be equivalent to bKey. If cKey is omitted, ordSetRelation() returns a null string ("") for the relation.
Returns
ordSetRelation() always returns NIL.
Description
ordSetRelation() relates the work area specified by nArea or cAlias (the child work area) to the current work area (the parent work area). Any existing relations remain active.
Relating work areas synchronizes the child work area with the parent work area. This is achieved by automatically repositioning the child work area whenever the parent work area moves to a new record. If there is a controlling order in the child work area, moving the parent work area causes an automatic seek operation in the child work area; the seek key is based on the expression specified by bKey and/or cKey. If the child work area has no controlling order, moving the parent work area causes an automatic "go to" in the child work area; the record number for the "go to" is based on the expression specified by bKey and/or cKey.
ordSetRelation() is identical to dbSetRelation() (and the SET RELATION command), but it also sets up a scope on the order in the child work area. This means that whenever you select the child work area, only the records related to the current parent record will be visible. This allows straightforward handling of one-to-many relationships. Refer to dbSetRelation() for more information.
Examples
■ This example displays each invoice with its related line
items:
USE LineTtem NEW VIA "DBFCDX"
SET ORDER TO TAG InvNo
USE Invoice NEW VIA "DBFCDX"
// Set a selective relation from Invoice into
// LineItem
ordSetRelation("LineItem", {|| Invoice->InvNo}, ;
"Invoice->InvNo")
GO TOP
DO WHILE !Eof()
? InvNo, InvDate // Display invoice fields
SELECT LineItem
// Only records for current invoice # are visible
LIST " ", PartNo, Qty, Price
SELECT Invoice // On to next invoice
SKIP
ENDDO
Move the record pointer to the next or previous unique key in the controlling order
Syntax
ordSkipUnique([<nDirection>]) → lSuccess
Arguments
nDirection specifies whether the function will skip to the next or previous key. Omitting this value or specifying it as 1 causes the record pointer to skip to the next unique key. Specifying a negative value makes it skip to the previous key.
Returns
ordSkipUnique() returns true (.T.) if successful; otherwise, it returns false (.F.).
Description
ordSkipUnique() allows you to make a non-unique order look like a unique order. Each time you use ordSkipUnique(), you are moved to the next (or previous) unique key exactly as if you were skipping through a unique order. This function eliminates the problems associated with maintaining a unique order, while providing you with fast access to unique keys.
By default, this function operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression.
Examples
■ This example uses ordSkipUnique() to build an array of unique
last names beginning with the letter "J":
FUNCTION LASTUNIQUE()
LOCAL aLast[0]
SET INDEX TO Last // Use the last name order
? ordIsUnique() // Result: .F.
SET SCOPE TO "J" // Only look at the J's
GO TOP
DO WHILE !Eof() // Add all the unique J
AAdd(aLast, Last) // last names to aLast
ordSkipUnique()
ENDDO
SET SCOPE TO // Clear the scope
RETURN aLast // Return array of
// unique J names
FORlCondition specifies the conditional set of records on which to create the order. Only those records that meet the condition are included in the resulting order. lCondition is an expression that may be no longer than 250 characters under the DBFNTX and DBFNDX drivers. The maximum value for these expressions is determined by the RDD. The FOR condition is stored as part of the order bag and used when updating or recreating the index using the ordCreate() or ORDREBUILD() functions. Duplicate key values are not added to the order bag.
Drivers that do not support the FOR condition produce an "unsupported" error.
The FOR clause provides the only scoping that is maintained for all database changes. All other scope conditions create orders that do not reflect database updates.
ALL specifies all orders in the current or specified work area. ALL is the default scope for ORDCOND().
WHILElCondition specifies another condition that must be met by each record as it is processed. As soon as the record is encountered that causes the condition to fail, the ordCreate() function terminates. If a WHILE clause is specified, the data is processed in the controlling order. The WHILE condition is transient (i.e., it is not stored in the file, not used for index updates, and not used for index updates and ORDREBUILD() purposes). The WHILE clause creates temporary orders, but these orders are not updated.
Drivers that do not support the WHILE condition produce an "unsupported" error.
Using the WHILE clause is more efficient and faster than using the FOR clause. The WHILE clause only processes data for which lCondition is true from the current position. The FOR clause, however, processes all data in the data source.
EVALbBlock evaluates a code block every nInterval, where nInterval is a value specified by the EVERY clause. The default value is 1. This is useful in producing a status bar or odometer that monitors the indexing progress. The return value of bBlock must be a logical data type. If bBlock returns false (.F.), indexing halts.
EVERYnInterval is a clause containing a numeric expression that modifies how often bBlock is EVALuated. The EVERY option of the EVAL clause offers a performance enhancement by evaluating the condition for every nth record instead of evaluating every record ordered. The EVERY keyword is ignored if you specify no EVAL conditions.
RECORDnRecord specifies the processing of the specified record.
NEXTnNumber specifies the portion of the database to process. If you specify NEXT, the database is processed in the controlling order for the nNumber number of identities. The scope is transient (i.e., it is not stored in the order and not used for ORDREBUILDing purposes).
REST specifies the processing of all records from the current position of the record pointer to the end of file (EOF).
DESCENDING specifies that the keyed pairs be sorted in decreasing order of value. If you create a DESCENDING index, you will not need to use the Descend() function during a SEEK. DESCENDING is an attribute of the file, where it is stored and used for ORDREBUILDing purposes.
Description
ORDCOND() is designed to set up the conditions for creating a new order (using the ordCreate() function) or rebuilding an existing order (using the ORDREBUILD() function). Do not use the ORDCOND() function if you wish to create or rebuild an entire index file; it is only used for setting particular conditions for the order.
ordCreate() or ORDREBUILD() should be used immediately following the ORDCOND() function.
If the DESCENDING clause is not specified, the order is then assumed to be ascending.
The EVAL clause lets you specify a code block to be evaluated as each record is placed in the order. The EVERY clause lets you modify how often bBlock is called. Instead of evaluating each record as it is placed in the order, evaluation only occurs as every nInterval records are placed in the order. This can be used, for example, to create a gauge that displays how far the ordCreate() or ORDREBUILD() has progressed so far.
The FOR clause provides the only order scoping that is permanent and that can be maintained across the life of the application. The string passed as the FOR condition is stored within the order for later use in maintaining the order. Though only accessing part of the database, orders created using this clause exist as long as the database is active. The FOR clause lets you create maintainable scoped orders.
The WHILE, NEXT, REST, and RECORD clauses process data from the current position of the database cursor in the default or specified work area. If you specify these clauses, the order list remains open and the active order is used to organize the database while it is being created. These clauses let you create temporary (non-maintainable) orders. orders created using these clauses contain records in which lCondition is true(.T.) at the location of the record pointer.
Examples
■ The following example creates a conditional order based on a
FOR clause. This index contains only records whose field TransDate
contains a date greater than or equal to January 1, 1992:
USE Invoice NEW
ORDCOND(FOR (Invoice->TransDate >= CTOD
("01/01/92")))
ordCreate("InvDate" , , "Invoice->TransDate")
■ The following example creates an order that calls a routine,
"MyMeter," during its creation:
USE Invoice NEW
ORDCOND(EVAL { | | MyMeter() } EVERY MTR_INCREMENT)
ordCreate("Invoice" , , "Invoice->Customer")
OS() returns the operating system name as a character string.
Description
OS() is an environment function that returns the name of the disk operating system under which the current workstation is operating. The name is returned in the form of the operating system name followed by the version number.
Examples
■ This example uses OS() to report the operating system under
which the current workstation is running:
? OS() // Result: DOS 6.0
Write a list of values to the standard error device
Syntax
OutErr(<exp list>) → NIL
Arguments
exp list is a list of values to display and can consist of any combination of data types including memo.
Returns
OutErr() always returns NIL.
Description
OutErr() is identical to OutStd() except that it writes to the standard error device rather than the standard output device. Output sent to the standard error device bypasses the CA-Clipper console and output devices as well as any DOS redirection. It is typically used to log error messages in a manner that will not interfere with the standard screen or printer output.
Examples
■ This example displays an error message along with the date and
time of occurrence to the screen:
OutErr("File lock failure", Date(), Time())
Write a list of values to the standard output device
Syntax
OutStd(<exp list>) → NIL
Arguments
exp list is a list of values to display and can consist of any combination of data types including memo.
Returns
OutStd() always returns NIL.
Description
OutStd() is a simple output function similar to QOut() except that it writes to the STDOUT device (instead of to the CA-Clipper console output stream). Programs with very simple output requirements (i.e., that perform no full-screen input or output) can use this function to avoid loading the terminal output subsystems. The header file Simplio.ch redefines the ? and ?? commands to use the OutStd() function.
Since OutStd() sends its output to the standard output device, the output can be redirected using the DOS redirection symbols (>, >, |). This lets you redirect output from a CA-Clipper program to a file or pipe. Refer to your PC/MS-DOS documentation for more information about this operating system facility.
Examples
■ This example uses OutStd() to display a list of expressions:
OutStd(Name, PadR(RTrim(City) + "," + ;
State, 20), ZipCode)
■ This example redirects the output of a CA-Clipper program to a
new file using the DOS redirection operator (>):
C>MYPROG > FILE.TXT
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, header file is Simplio.ch.
exp is a character, numeric, or date value to be padded with a fill character.
nLength is the length of the character string to be returned.
cFillChar is the character with which to pad exp. If not specified, the default is a space character.
Returns
PadC(), PadL(), and PadR() return the result of exp as a character string padded with cFillChar to a total length of nLength.
Description
PadC(), PadL(), and PadR() are character functions that pad character, date, and numeric values with a fill character to create a new character string of a specified length. PadC() centers exp within nLength adding fill characters to the left and right sides; PadL() adds fill characters on the left side; and PadR() adds fill characters on the right side. If the length of exp exceeds nLength, all of the Pad() functions truncate cPaddedString to nLength.
PadC(), PadL(), and PadR() display variable length strings within a fixed length area. They can be used, for instance, to ensure alignment with consecutive ?? commands. Another use is to display text to a fixed- width screen area assuring that previous text is completely overwritten.
■ This example uses PadR() to format a record number display on
a status line filling the allocated space:
IF Eof()
@ 23, 45 PadR("EOF/" + LTrim(Str(LastRec())), 20)
ELSEIF Bof()
@ 23, 45 PadR("BOF/" + LTrim(Str(LastRec())), 20)
ELSE
@ 23, 45 SAY PadR("Record " + LTrim(Str(RecNo()) ;
+ "/" + LTrim(Str(LastRec())), 20)
ENDIF
PACK is a database command that removes all records marked for deletion from the current database file, REINDEXes all active indexes in the current work area, and recovers all the physical space occupied by the deleted records. During its operation, PACK does not create any backup files, although the associated REINDEX operation may. After the PACK command terminates, the record pointer is reset to the first logical record in the current work area.
In a network environment, PACK requires that the current database be USEd EXCLUSIVEly. If this condition is not met when PACK is invoked, CA-Clipper generates a runtime error.
Note that PACKing large database files can be a time-consuming process and may not be feasible in a high-volume transaction system on a network. By modifying the system design, you can remove the necessity of physically removing records from the database file altogether. See the "Network Programming" chapter in the Programming and Utilities Guide for more information.
Examples
■ The following example shows the result of a simple PACK:
USE Sales NEW
? LastRec() // Result: 84
//
DELETE RECORD 4
PACK
? LastRec() // Result: 83
idPrivate list is one or more parameter variables separated by commas. The number of receiving variables does not have to match the number of arguments passed by the calling procedure or user-defined function.
Description
The PARAMETERS statement creates private variables to receive passed values or references. Receiving variables are referred to as parameters. The values or references actually passed by a procedure or user-defined function invocation are referred to as arguments.
When a PARAMETERS statement executes, all variables in the parameter list are created as private variables and all public or private variables with the same names are hidden until the current procedure or user-defined function terminates. A PARAMETERS statement is an executable statement and, therefore, can occur anywhere in a procedure or user-defined function, but must follow all compile-time variable declarations, such as FIELD, LOCAL, MEMVAR, and STATIC.
Parameters can also be declared as local variables if specified as a part of the PROCEDURE or FUNCTION declaration statement (see the example). Parameters specified in this way are referred to as formal parameters. Note that you cannot specify both formal parameters and a PARAMETERS statement with a procedure or user-defined function definition. Attempting to do this results in a fatal compiler error and an object file is not generated.
In CA-Clipper the number of arguments and parameters do not have to match. If you specify more arguments than parameters, the extra arguments are ignored. If you specify fewer arguments than parameters, the extra parameters are created with a NIL value. If you skip an argument, the corresponding parameter is initialized to NIL. The PCount() function returns the position of the last argument passed in the list of arguments. This is different from the number of parameters passed since it includes skipped parameters.
For more information on passing parameters, refer to the Functions and Procedures section in the "Basic Concepts" chapter of the Programming and Utilities Guide.
Examples
■ This user-defined function receives values passed into private
parameters with a PARAMETERS statement:
FUNCTION MyFunc
PARAMETERS cOne, cTwo, cThree
? cOne, cTwo, cThree
RETURN NIL
■ This example is similar, but receives values passed into local
variables by declaring the parameter variables within the FUNCTION
declaration:
FUNCTION MyFunc( cOne, cTwo, cThree )
? cOne, cTwo, cThree
RETURN NIL
Return the current column position of the printhead
Syntax
PCol() → nColumn
Returns
PCol() returns an integer numeric value representing the last printed column position, plus one. The beginning column position is zero.
Description
PCol() is a printer function that reports the column position of the printhead after the last print operation. PCol() is updated only if either SET DEVICE TO PRINTER or SET PRINTER ON is in effect. PCol() is the same as Col() except that it relates to the printer rather than the screen. PCol() is updated in the following ways:
■ Application startup sets PCol() to zero
■ EJECT resets PCol() to zero
■ A print operation sets PCol() to the last column print
position plus one
■ SetPRC() sets PCol() to the specified column position
PCol(), used with PRow(), prints a value relative to the last value printed on the same line. This makes it easier to align columns when printing a columnar report. A value is printed in the next column by specifying its position as PCol() + column offset. Note that PCol() is effective for alignment only if the column values are fixed-width. To guarantee fixed-width column values, format the output using Transform(), the PICTURE clause of @...SAY, or any of the Pad() functions.
Notes
■ Printer control codes: Sending control codes to the printer
causes PCol() to become out of sync with the printhead position. Although control codes do not print, this discrepancy happens because CA-Clipper counts all characters sent to the printer regardless of how the printer treats them. To make the necessary adjustment, save the current PRow() and PCol() values, send the control codes, and then use SetPRC() to restore the original PRow() and PCol() values.
■ SET MARGIN: PCol() cannot reliably be used with SET MARGIN to
print with @...SAY. When printing with @...SAY, the current MARGIN value is always added to the specified column position before output is sent to the printer. This effectively adds the MARGIN value to PCol() for each invocation of @...SAY to the same print line.
Examples
■ In this example, PCol() creates a simple report that prints a
listing of Customer names, addresses, and phone numbers:
LOCAL nLine := 99, nPage := 1
USE Customer INDEX CustName NEW
SET DEVICE TO PRINTER
DO WHILE !Eof()
IF nLine > 55
PageTop(nPage)
nLine := 1
nPage++
ENDIF
@ nLine, 10 SAY CustName
@ nLine, PCol() + 2;
SAY RTrim(City) + ", " + RTrim(State) + ZipCode;
PICTURE Replicate("X", 35)
@ nLine, PCol() + 2;
SAY Phone;
PICTURE "@R (999) 999-9999"
nLine++
SKIP
ENDDO
SET DEVICE TO SCREEN
CLOSE
Determine the position of the last actual parameter passed
Syntax
PCount() → nLastArgumentPos
Returns
PCount() returns, as an integer numeric value, the position of the last argument passed. If no arguments are passed, PCount() returns zero.
Description
PCount() reports the position of the last argument in the list of arguments passed when a procedure or user-defined function is invoked. This information is useful when determining whether arguments were left off the end of the argument list. Arguments skipped in the middle of the list are still included in the value returned.
To determine if a parameter did not receive a value, test it for NIL. Skipped parameters are uninitialized and, therefore, return NIL when accessed. Another method is to test parameters with the ValType() function. This can establish whether the argument was passed and enforce the correct type at the same time. If a parameter was not supplied, a default value can be assigned.
For more information on passing parameters, refer to the "Basic Concepts" chapter in the Programming and Utilities Guide.
Examples
■ This example is a user-defined function that opens a database
file and uses PCount() to determine whether the calling procedure
passed the name of the database file to be opened. If the name was
not passed, OpenFile() asks for the name:
FUNCTION OpenFile( cFile )
IF PCount() = 0
ACCEPT "File to use: " TO cFile
ENDIF
USE (cFile)
RETURN (NetErr())
Place items on the top bar menu or another pop-up menu.
Methods link
Class Function
Popup() Create a new PopUp object
Popup([nTop], [nLeft], [nBottom], [nRight])
→ oPopUp
Arguments
nTop is a numeric value that indicates the top screen row of the pop-up menu. If omitted, PopUpMenu:top is set to an appropriate value relative to nBottom that allows as many items as possible to show. If nBottom is also omitted, PopUpMenu:top is set to center the menu vertically on the screen. The default value is determined the first time the pop-up menu is displayed.
When the pop-up menu is a child of another menu, its top variable will be automatically set by the parent menu regardless of whether nTop is omitted.
nLeft is a numeric value that indicates the left screen column of the pop-up menu. If omitted, PopUpMenu:left is set to an appropriate value relative to nRight that allows as many menu columns as possible to show. If nRight is also omitted, PopUpMenu:left is set to center the menu horizontally on the screen. The default value is determined the first time the pop-up menu is displayed.
When the pop-up menu is a child of another menu, its left variable will be automatically set by the parent menu regardless of whether nLeft is omitted.
nBottom is a numeric value that indicates the bottom screen row of the pop-up menu. If omitted, PopUpMenu:bottom is set to an appropriate value relative to nTop that allows as many items as possible to show. If nTop is also omitted, PopUpMenu:bottom is set to center the menu vertically on the screen. The default value is determined the first time the pop-up menu is displayed.
When the pop-up menu is a child of another menu, its bottom variable will be automatically set by the parent menu regardless of whether nBottom is omitted.
nRight is a numeric value that indicates the right screen column of the pop-up menu. If omitted, PopUpMenu:right is set to an appropriate value relative to nLeft that allows as many menu columns as possible to show. If nLeft is also omitted, PopUpMenu:right is set to center the menu horizontally on the screen. The default value is determined the first time the pop-up menu is displayed.
When the pop-up menu is a child of another menu, its right variable will be automatically set by the parent menu regardless of whether nRight is omitted.
Returns
Returns a PopUpMenu object when all of the required arguments are present; otherwise, Popup() returns NIL.
Exported Instance Variables
border An optional string used when drawing the menu's border
border (Assignable)
Contains an optional string that is used when drawing a border around the pop-up menu. Its default value is B_SINGLE + SEPARATOR_SINGLE. The string must contain either zero or exactly eleven characters. The first eight characters represent the border of the pop-up menu and the final three characters represent the left, middle, and right characters for the menu item separators. The eight characters which represent the pop-up menu border begin at the upper-left corner and rotate clockwise as follows: upper-left corner, top, upper-right corner, right, bottom, bottom-left corner, and left.
bottom A numeric value indicating bottommost screen row
bottom (Assignable)
Contains a numeric value that indicates the bottommost screen row where the pop-up menu is displayed. If not specified when the PopUpMenu object is instantiated, PopUpMenu:bottom contains NIL until the first time it is displayed.
cargo User-definable variable
cargo (Assignable)
Contains a value of any type that is ignored by the PopUpMenu object. PopUpMenu:cargo is provided as a user-definable slot allowing arbitrary information to be attached to a PopUpMenu object and retrieved later.
colorSpec Display attributes string
colorSpec (Assignable)
Contains a character string that indicates the color attributes that are used by the pop-up menu's display() method. The string must contain six color specifiers.
PopUpMenu Color Attributes
Position Applies To Default Value from
in colorSpec System Color Setting
1 The pop-up menu items that are not Unselected
selected
2 The selected pop-up menu item Enhanced
3 The accelerator key for unselected Background
pop-up menu items
4 The accelerator key for the selected Enhanced
pop-up menu item
5 Disabled pop-up menu items Standard
6 The pop-up menu's border Border
Note: The colors available to a DOS application are more limited than those for a Windows application. The only colors available to you here are listed in the drop-down list box of the Workbench Properties window for that item.
current Numeric value indicating the selected item
current
Contains a numeric value that indicates which item is selected. PopUpMenu:current contains 0 when the pop-up menu is not open.
itemCount Numeric value indicating the number of items in the object
itemCount
Contains a numeric value that indicates the total number of items in the PopUpMenu object.
left Numeric value indicating the leftmost screen row
left (Assignable)
Contains a numeric value that indicates the leftmost screen row where the pop-up menu is displayed. If not specified when the PopUpMenu object is instantiated, PopUpMenu:left contains NIL until the first time it is displayed.
right Numeric value indicating the rightmost screen row
right (Assignable)
Contains a numeric value that indicates the rightmost screen row where the pop-up menu is displayed. If not specified when the PopUpMenu object is instantiated, PopUpMenu:right contains NIL until the first time it is displayed.
top Numeric value indicating the topmost screen row
top (Assignable)
Contains a numeric value that indicates the topmost screen row where the pop-up menu is displayed. If not specified when the PopUpMenu object is instantiated, PopUpMenu:top contains NIL until the first time it is displayed.
width Numeric value indicating width requirements
width
Contains a numeric value that indicates the width required to display all of the pop-up menu's items in their entirety. This includes check marks and submenu indicators.
Exported Methods
addItem() Appends new item to pop-up menu
oPopUp:addItem(oMenuItem) → self
oMenuItem is a MenuItem object.
addItem() is a method of the PopUpMenu class that is used for appending a new item to a pop-up menu.
close() Deactivates a pop-up menu
oPopUp:close([lCloseChild]) → self
lCloseChild is a logical value that indicates whether PopUpMenu:close() should deactivate the pop-up menu in its selected item, which in turn deactivates the pop-up menu in its selected item and so on. This is useful for nested menus where multiple levels of choices are presented. A value of true (.T.) indicates that child pop-up menu items should be closed. A value of false (.F.) indicates that child pop-up menu items should not be closed. The default value is true.
close() is a method of the PopUpMenu class that is used for deactivating a pop-up menu. When called, PopUpMenu:close() performs three operations. First, if the value of lCloseChild is not false (.F.) , close() determines if its selected menu item contains a PopUpMenu object. If so, it calls its selected menu item's close() method. Second, close() restores the previous contents of the region of the screen that it occupies. Third, close() sets its selected item to 0.
Note: This message only has meaning when the pop-up menu is open.
delItem() Removes an item from a pop-up menu
oPopUp:delItem(nPosition) → self
nPosition is a numeric value that indicates the position in the pop-up menu of the item to be deleted.
delItem() is a method of the PopUpMenu class that is used for removing an item from a pop-up menu.
display() Shows a pop-up menu including its items on the screen
oPopUp:display() → self
display() is a method of the PopUpMenu class that is used for showing a pop-up menu including its items on the screen. display() uses the values of the following instance variables to correctly show the list in its current context, in addition to providing maximum flexibility in the manner a pop-up menu appears on the screen:
getAccel() Determines if a key press is interpreted as a user request
oPopUp:getAccel(nInkeyValue) → nPosition
nInkeyValue is a numeric value that indicates the inkey value to be checked.
Returns a numeric value that indicates the position in the pop-up menu of the first item whose accelerator key matches that which is specified by nInkeyValue. The accelerator key is defined using the & character in MenuItem:caption.
getAccel() is a method of the PopUpMenu class that is used for determining whether a key press should be interpreted as a user request to evoke the Data variable of a particular pop-up menu item.
getFirst() Determines position of first selectable item in a menu
oPopUp:getFirst() → nPosition
getFirst() is a method of the PopUpMenu class that is used for determining the position of the first selectable item in a pop-up menu. The term selectable is defined as a menu item that is enabled and whose caption is not a menu separator.
Returns a numeric value that indicates the position within the pop-up menu of the first selectable item. getFirst() returns 0 in the event that the pop-up menu does not contain a selectable item.
Note: getFirst() does not change the currently selected menu item. In order to change the currently selected pop-up menu item, you must call the PopUpMenu:select() method.
getItem() Access a MenuItem object after it has been added to a menu
oPopUp:getItem(nPosition) → oMenuItem
nPosition is a numeric value that indicates the position in the pop-up menu of the item that is being retrieved.
Returns the MenuItem object at the position in the pop-up menu specified by nPosition or NIL when nPosition is invalid.
getItem() is a method of the PopUpMenu class that is used for accessing a MenuItem object after it has been added to a pop-up menu.
getLast() Determines position of last selectable item in a menu
oPopUp:getLast() → nPosition
Returns a numeric value that indicates the position within the pop-up menu of the last selectable item. getLast() returns 0 in the event that the pop-up menu does not contain a selectable item.
getLast() is a method of the PopUpMenu class that is used for determining the position of the last selectable item in a pop-up menu. The term selectable is defined as a menu item that is enabled and whose caption is not a menu separator.
Note: getLast() does not change the currently selected menu item. In order to change the currently selected pop-up menu item, you must call the PopUpMenu:select() method.
getNext() Determines position of next selectable item in a menu
oPopUp:getNext() → nPosition
Returns a numeric value that indicates the position within the pop-up menu of the next selectable item. getNext() returns 0 in the event that the current item is the last selectable item or the pop-up menu does not contain a selectable item.
getNext() is a method of the PopUpMenu class that is used for determining the position of the next selectable item in a pop-up menu. getNext() searches for the next selectable item starting at the item immediately after the current item. The term selectable is defined as a menu item that is enabled and whose caption, is not a menu separator.
Note: getNext() does not change the currently selected menu item. In order to change the currently selected pop-up menu item, you must call the PopUpMenu:select() method.
getPrev() Determines position of previous selectable item in a menu
oPopUp:getPrev() → nPosition
Returns a numeric value that indicates the position within the pop-up menu of the previous selectable item. getPrev() returns 0 in the event that the current item is the first selectable item or the pop- up menu does not contain a selectable item.
getPrev() is a method of the PopUpMenu class that is used for determining the position of the previous selectable item in a pop-up menu. getPrev() searches for the previous selectable item starting at the item immediately before the current item. The term selectable is defined as a menu item that is enabled and whose caption is not a menu separator.
Note: getPrev() does not change the currently selected menu item. In order to change the currently selected pop-up menu item, you must call the PopUpMenu:select() method.
getShortct() Determines if a key press is interpreted as a user request
oPopUp:getShortct(nInkeyValue) → nPosition
nInkeyValue is a numeric value that indicates the inkey value to be checked.
Returns a numeric value that indicates the position in the pop-up menu of the first item whose shortcut key matches that which is specified by nInkeyValue. The shortcut key is defined using the MenuItem:shortcut instance variable.
getShortct() is a method of the PopUpMenu class that is used for determining whether a keystroke should be interpreted as a user request to select a particular pop-up menu item.
HitTest() Indicates position of mouse cursor relative to pop-up menu
oPopUp:hitTest(nMouseRow, nMouseCol)
→ nHitStatus
nMouseRow is a numeric value that indicates the current screen row position of the mouse cursor.
nMouseCol is a numeric value that indicates the current screen column position of the mouse cursor.
Returns a numeric value that indicates the relationship of the mouse cursor with the pop-up menu.
Applicable Hit Test Return Values
Value Constant Description
> 0 Not Applicable The position in the pop-up menu of the item
whose region the mouse is within
0 HTNOWHERE The mouse cursor is not within the region of
the screen that the menu occupies
-1 HTTOPLEFT The mouse cursor is on the top left corner of
the pop-up menu's border
-2 HTTOP The mouse cursor is on the pop-up menu's top
border
-3 HTTOPRIGHT The mouse cursor is on the top right corner of
the pop-up menu's border
-4 HTRIGHT The mouse cursor is on the pop-up menu's right
border
-5 HTBOTTOMRIGHT The mouse cursor is on the bottom right corner
of the pop-up menu's border
-6 HTBOTTOM The mouse cursor is on the pop-up menu's bottom
border
-7 HTBOTTOMLEFT The mouse cursor is on the bottom left corner
of the pop-up menu's border
-8 HTLEFT The mouse cursor is on the pop-up menu's left
border
-4098 HTSEPARATOR The mouse is on a menu separator line
Button.ch contains manifest constants for the PopUpMenu:hitTest() return value.
HitTest() is a method of the PopUpMenu class that is used for determining if the mouse cursor is within the region of the screen that the pop-up menu occupies.
insItem() Inserts a new item to a pop-up menu
oPopUp:insItem(nPosition, oMenuItem) → self
nPosition is a numeric value that indicates the position at which the new menu item is inserted.
oMenuItem is a MenuItem object.
insItem() is a method of the PopUpMenu class that is used for inserting a new item within a pop-up menu.
isOpen() Determines if a pop-up menu is open
oPopUp:isOpen() → lIsOpen
Returns a logical value that indicates whether the pop-up menu is open or not. A value of true (.T.) indicates that the pop-up menu is open, a value of false (.F.) indicates that it is closed.
isOpen() is a method of the PopUpMenu class that is used for determining if a pop-up menu is open. A pop-up menu is considered open during the period after calling its open() method and before calling its close() method
open() Activates a pop-up menu
oPopUp:open() → self
open() is a method of the PopUpMenu class that is used for activating a pop-up menu. When called, open() performs two operations. First, open() saves the previous contents of the region of the screen that the pop-up menu occupies. Second, open() calls its pop-up menu's display() method.
Note: This message only has meaning when the pop-up menu is closed.
nPosition is a numeric value that indicates the position in the pop-up menu of the item to be selected.
Select() is a method of the PopUpMenu class that is used for changing the selected item. Its state is typically changed when one of the arrow keys is pressed or the mouse's left button is pressed when its cursor is within the pop-up menu's screen region.
setItem() Replaces a MenuItem object after it has been added to a menu
oPopUp:setItem(nPosition, oMenuItem) → self
nPosition is a numeric value that indicates the position in the pop-up menu of the item that is being retrieved.
oMenuItem is the MenuItem object that replaces the one in the pop- up menu specified by nPosition.
setItem() is a method of the PopUpMenu class that is used for replacing a MenuItem object after it has been added to a pop-up menu. After the setItem() method is called, the display()method needs to be called in order to refresh the menu. It is not allowed to call the display() method for the currently opened pop-up menu in the code block of the menu items. Otherwise, there are screen refresh problems especially if the code block has also increased the number of items in the pop-up menu.
Examples
See the Menu.prg sample file in the \CLIP53\SOURCE\SAMPLE directory.
This example demonstrates combining TopBarMenu, PopUpMenu, and MenuItem
objects to create a menu with a number of available choices. See
"Introduction to the Menu System" in the Programming and Utilities Guide
for more information about using this class.
Return the source line number of the current or previous activation
Syntax
ProcLine([<nActivation>]) → nSourceLine
Arguments
nActivation is a numeric value that specifies which activation to query. Zero refers to the current activation, one refers to the previous activation, etc. If not specified, the default value is zero.
Returns
ProcLine() returns the line number of the last line executed in a currently executing procedure, function, or code block as an integer numeric value. If the /L compiler option suppresses line number information, ProcLine() always returns zero.
Description
ProcLine() queries the CA-Clipper activation stack to determine the last line executed in a currently executing procedure, user-defined function, or code block. The activation stack is an internal structure that maintains a record of each procedure, function, or code block invocation. A line number is relative to the beginning of the original source file. A line includes a comment, blank line, preprocessor directive, and a continued line. A multistatement line is counted as a single line.
For the current activation, ProcLine() returns the number of the current line. For a previous activation, ProcLine() returns the number of the line that invoked the procedure or a user-defined function in which ProcLine() is invoked.
If the activation being queried is a code block evaluation, ProcLine() returns the line number of the procedure in which the code block was originally defined.
ProcLine() is used with ProcName() to report debugging information.
Examples
■ In this example, ProcLine() returns the line number for the
current activation, followed by the line number of the previous
activation:
// First line of source file
MyFunction()
RETURN
FUNCTION MyFunction
? ProcLine() // Result: 6 (current activation)
? ProcLine(1) // Result: 2 (previous activation)
RETURN NIL
Return the name of the current or previous procedure or user-defined function
Syntax
ProcName([<nActivation>]) → cProcedureName
Arguments
nActivation specifies which activation to query. A value of zero refers to the current activation, a value of one refers to the previous activation, etc. If unspecified, the default value is zero.
Returns
ProcName() returns the name of a currently executing procedure, function, or code block, as a character string.
Description
ProcName() queries the CA-Clipper activation stack to determine the name of a currently executing procedure, user-defined function, or code block. The activation stack is an internal structure that maintains a record of each procedure, function, or code block invocation.
For the current activation, ProcName() returns the name of the current procedure or user-defined function. For a previous activation, ProcName() returns the name of the procedure or user-defined function that invoked the current procedure.
If the activation being queried is a code block evaluation, ProcName() returns the name of the procedure or user-defined function that defined the code block, preceded by "b". If the activation being queried is a memvar, ProcName() returns the name preceded by "M->".
ProcName() is used with ProcLine() to report debugging information.
Examples
■ This example is a user-defined function you can call during a
debugging phase of program development in order to display the
activation stack with line numbers:
FUNCTION ListStack( cMessage )
LOCAL nActivation := 1
? cMessage
DO WHILE !(ProcName(nActivation) == "")
? "Called from:", ProcName(nActivation),;
"(" + LTrim(Str(ProcLine(nActivation))) + ")"
nActivation++
ENDDO
QUIT
RETURN NIL
Create and initialize private memory variables and arrays
Syntax
PRIVATE <identifier> [[:= <initializer>], ... ]
Arguments
identifier is the name of a private variable or array to create. If the identifier is followed by square brackets ([ ]), an array is created and assigned to the identifier. When the identifier specification indicates an array, the syntax for specifying the number of elements for each dimension can be array[nElements, nElements2,...] or array[nElements][nElements2]... The maximum number of elements per dimension is 4096. The maximum number of dimensions is limited only by available memory.
initializer is the optional assignment of a value to a new private variable. An array cannot be given values with an initializer. An initializer for a private variable consists of the inline assignment operator (:=) followed by any valid CA-Clipper expression including a literal array. If no explicit initializer is specified, the variable is initialized to NIL. In the case of an array, each element is initialized to NIL.
You can create and, optionally, initialize a list of variables and arrays with one PRIVATE statement if the definitions are separated by commas.
Description
The PRIVATE statement creates variables and arrays visible within the current and invoked procedures or user-defined functions. This class of variable is said to have dynamic scope. Private variables exist for the duration of the active procedure or until explicitly released with CLEAR ALL, CLEAR MEMORY, or RELEASE. When a private variable or array is created, existing and visible private and public variables of the same name are hidden until the current procedure or user-defined function terminates.
Attempting to specify a PRIVATE variable that conflicts with a previous FIELD, LOCAL, or STATIC declaration of the same name results in a fatal compiler error. This is true regardless of the scope of the declaration.
PRIVATE statements are executable statements and, therefore, must be specified within the body of a procedure or user-defined function and must follow all variable declarations, such as FIELD, LOCAL, MEMVAR, and STATIC.
In addition to the PRIVATE statement, private variables are also created in two other ways:
■ Assignment to a variable that does not exist or is not visible
will create a private variable
■ Parameters received using the PARAMETERS statement are created
as private variables with the same lifetime and visibility
No more than 2048 private and public variables and arrays can simultaneously exist in a single program.
For more information on variable declarations and scoping, refer to the Variables section in the "Basic Concepts" chapter of the Programming and Utilities Guide.
Notes
■ Compatibility: The ALL, LIKE, and EXCEPT clauses of the
PRIVATE statement supported by other dBASE dialects are not supported by CA-Clipper.
Examples
■ This example creates two PRIVATE arrays and three other
PRIVATE variables:
PRIVATE aArray1[10], aArray2[20], var1, var2, var3
■ This example creates a multidimensional private array using
each element addressing convention:
PRIVATE aArray[10][10][10], aArray2[10, 10, 10]
■ This example uses PRIVATE statements to create and initialize
arrays and variables:
PRIVATE aArray := { 1, 2, 3, 4 }, ;
aArray2 := Array(12, 24)
PRIVATE cChar := Space(10), cColor := SetColor()
PRow() returns an integer numeric value that represents the number of the current line sent to the printer. The beginning row position is zero.
Description
PRow() is a printer function that reports the row position of the printhead after the last print operation. PRow() is updated only if either SET DEVICE TO PRINTER or SET PRINTER ON is in effect. PRow() is like Row() except that it relates to the printer rather than the screen. PRow() is updated in the following ways:
■ Application startup sets PRow() to zero
■ EJECT resets PRow() to zero
■ A print operation sets PRow() to the last row print position
■ SetPRC() sets PRow() to the specified row position
PRow() used with PCol() prints a value to a new row relative to the last row printed. If the printhead is positioned to a new row with a control code, a line feed (Chr(10)), or form feed (Chr(12)), PRow() is not updated and, therefore, will not return the expected value. To prevent this discrepancy, reset PRow() to the correct value with SetPRC() after sending any of these characters to the printer.
Examples
■ This example uses PRow() and SetPRC() to create a simple one-
across label program that prints with @...SAY instead of ?:
USE Customer INDEX CustName NEW
SET DEVICE TO PRINTER
SetPRC(2, 0)
DO WHILE !Eof()
@ PRow(), 3 SAY CustName
@ PRow() + 1, 3 SAY RTrim(City) + ",;
" + RTrim(State) + ZipCode
@ PRow() + 1, 3 SAY Phone PICTURE "@R ;
(999) 999-9999"
SetPRC(2, 0)
SKIP
ENDDO
SET DEVICE TO SCREEN
CLOSE
idProcedure is the name of the procedure to be declared. Procedure names can be any length, but only the first 10 characters are significant. Names can contain any combination of characters, numbers, or underscores, but leading underscores are reserved.
idParam list is the declaration of one or more parameter variables. Variables specified in this list are declared local.
STATIC PROCEDURE declares a procedure that can be called only by procedures and user-defined functions declared in the same program (.prg) file.
FIELD declares a list of identifiers, idField list, to use as field names whenever encountered. If the IN clause is specified, referring to the declared name, idAlias is a reference to the appropriate work area of the specified database.
LOCAL declares and optionally initializes a list of variables or arrays whose visibility and lifetime is the current procedure.
identifier, identifier list is a label or labels used as variable or array names. If the identifier is followed by square brackets ([ ]), it is created as an array. If the identifier is an array, the syntax for specifying the number of elements for each dimension can be array[nElements, nElements2,...] or array[nElements][nElements2]... The maximum number of elements per dimension is 4096. The maximum number of dimensions per array is limited only by available memory.
initializer is the value to which an optional inline assignment sets the identifier variable—essentially, the assignment operator, (:=) —followed by any valid CA-Clipper expression, including a literal array. If no initializer is specified, variables are initialized to NIL. In the case of arrays, all element are initialized to NIL.
MEMVAR declares a list of identifiers, identifier list, to use as private or public memory variables or arrays whenever encountered.
STATIC declares and, optionally, initializes a list of variables or arrays whose visibility is the current procedure and whose lifetime is the duration of the program.
RETURN passes control back to the calling procedure or user-defined function. If a RETURN is not specified, control passes back to the calling routine when the procedure definitions ends. In all cases, the compiler terminates the procedure definition when it encounters another PROCEDURE statement, FUNCTION statement, or end of file character.
Description
The PROCEDURE statement declares a procedure and an optional list of local variables to receive parameters passed from a calling routine. A procedure is a subprogram comprised of a set of declarations and statements executed whenever you refer to idProcedure, followed by an open and close parentheses pair or with the DO statement. A procedure definition begins with a PROCEDURE statement and ends with the next PROCEDURE statement, FUNCTION statement, or end of file.
Procedures that encapsulate computational blocks of code provide readability and modularity, isolate change, and help manage complexity.
A procedure in CA-Clipper is the same as a user-defined function, with the exception that it always returns NIL. Each procedure must begin with a PROCEDURE statement and may, optionally, contain a RETURN statement to return control to the calling procedure or user-defined function. A RETURN statement, however, is not required. Procedure declarations cannot be nested within other procedure definitions.
The visibility of procedure names falls into two classes. Procedures that are visible anywhere in a program are referred to as public procedures and declared with a PROCEDURE statement. Procedures that are visible only within the current program (.prg) file are referred to as static procedures and declared with a STATIC PROCEDURE statement. Static procedures have filewide scope.
Static procedures are quite useful for a number of reasons. First, they limit visibility of a procedure name thereby restricting access to the procedure. Because of this, subsystems defined within a single program (.prg) file can provide an access protocol with a series of public procedures and conceal the implementation details of the subsystem within static procedures and functions. Second, since the static procedure references are resolved at compile time, they preempt references to public procedures and functions which are resolved at link time. This ensures that, within a program file, a reference to a static procedure executes that procedure if there is a name conflict with a public procedure or function.
For more information on procedures, variable declarations, and parameter passing, refer to the "Basic Concepts" chapter in the Programming and Utilities Guide.
Notes
■ Calling a procedure: There are two ways to call a procedure
in CA-Clipper. The first and preferred way is the function-calling convention. Here you call the procedure as you would a CA-Clipper function on a line by itself:
idProcedure([argument list])
The second and obsolete way is the command-calling convention using the DO...WITH command. The two methods of calling procedures differ only in the default method of passing parameters. The function- calling convention passes variables by value as a default, whereas the command-calling convention passes them by reference as a default.
A procedure can also be called as an aliased expression if it is prefaced with an alias and invoked using the function-calling convention, like this:
idAlias ->(idProcedure(argument list))
When called as an aliased expression, the work area associated with idAlias is selected, the procedure is executed, and then the original work area is reselected. Like an expression or function, an aliased procedure can be specified on a line by itself.
A procedure in CA-Clipper may call itself recursively. This means you can call a procedure in the same procedure definition.
■ Parameters: Procedures like user-defined functions can
receive parameters passed from a calling procedure, user-defined function, or the DOS command line. A parameter is a place for a value or reference. In CA-Clipper there are two ways to receive parameters: a list of local variable names can be declared as a part of the PROCEDURE declaration (referred to as formal parameters), or a list of private variables can be specified in a separate PARAMETERS statement. Note that you cannot mix a declaration of formal parameters with a PARAMETERS statement. Attempting this will cause a fatal compiler error.
Procedures receive parameters in the order passed. In CA-Clipper the number of parameters need not match the number of arguments passed. Arguments can be skipped or left off the end of the argument list. A parameter not receiving a value or reference is initialized to NIL. If arguments are specified, PCount() returns the position of the last argument passed.
Parameters specified in a procedure can receive arguments passed by value or by reference. The default method for expressions and variables depends on the calling convention. With the function-calling convention, the default passing method for expressions and variables is by value. This includes variables containing references to arrays and objects. With the command- calling convention, the default method for passing variables is by reference except for field variables, which are always passed by value. Whenever a field variable is passed, it must be specified enclosed in parentheses unless declared with the FIELD statement. Failure to do so will generate a runtime error.
Examples
■ This example shows a skeleton of a typical CA-Clipper
procedure that uses lexical variables:
PROCEDURE Skeleton( cName, cClassRoom, nBones, ;
nJoints )
LOCAL nCrossBones, aOnHand := {"skull", ;
"metacarpals"}
STATIC nCounter := 0
.
. <executable statements>
.
RETURN
■ This example determines whether an argument was skipped by
comparing the parameter to NIL:
PROCEDURE MyProc( param1, param2, param3 )
IF param2 != NIL
param2 := "default value"
ENDIF
.
. <statements>
.
RETURN
■ This example invokes the procedure, UpdateAmount(), as an
aliased expression:
USE Invoices NEW
USE Customer NEW
Invoices->(UpdateAmount(Amount + Amount * nInterest))
Places a push button at the indicated position on the screen.
Methods link
Class Function
PushButton() Create a new PushButton object
PushButton(nRow, nColumn, [cCaption])
→ oPushButton
Arguments
nRow is a numeric value that indicates the screen row of the push button.
nColumn is a numeric value that indicates the screen column of the push button.
cCaption is an optional character string that describes the push button on the screen. If omitted, the default is an empty string.
Returns
Returns a PushButton object when all of the required arguments are present; otherwise PushButton() returns NIL.
Exported Instance Variables
bitmap The bitmap file to display on the button
bitmap (Assignable)
Contains a character string that indicates a bitmap file to be displayed on the button. Drive and directory names are not allowed; the file name extension is required. A bitmap file can be stored as a file on disk or in a bitmap library. If stored as a file, the file must reside in the same directory as the application. If stored in a bitmap library, the library must reside in the same directory as the application and it also must have the same name as the application with a .BML extension.
CA-Clipper will search for the file name first and, if it is not found, search in the bitmap library second. If no file is found either on disk or in the library, no bitmap will be displayed. This instance variable only affects applications running in graphic mode and is ignored in text mode.
bmpXOff Indicates the horizontal offset where the bitmap is displayed
bmpXOff (Assignable)
Contains a numeric value that indicates the offset where the bitmap is displayed. This instance variable represents the number of pixels in the x direction (horizontally) from the left edge of the button where the bitmap will be displayed. If this instance variable is not supplied, the bitmap will be placed at the left edge of the button. This instance variable only affects applications running in graphic mode and is ignored in text mode.
bmpYOff Indicates the vertical offset where the bitmap is displayed
bmpYOff (Assignable)
Contains a numeric value that indicates the offset where the bitmap is displayed. This instance variable represents the number of pixels in the y direction (vertically) from the top edge of the button where the bitmap will be displayed. If this instance variable is not supplied, the bitmap will be placed at the top edge of the button. This instance variable only affects applications running in graphic mode and is ignored in text mode.
buffer Logical value indicating the push button has been pushed
buffer
Contains a logical value indicating that the push button has been pushed. A value of true (.T.) indicates that the push button has been pushed; otherwise, a value of false (.F.) indicates that it has not.
caption Character string describing the push button on the screen
caption (Assignable)
Contains a character string that describes the push button on the screen.
When present, the & character specifies that the character immediately following it in the caption is the push button's accelerator key. The accelerator key provides a quick and convenient mechanism for the user to move input focus from one data input control to a push button. The user performs the selection by pressing the Alt key in combination with an accelerator key. The case of an accelerator key is ignored.
capXOff Indicates the horizontal offset where caption is displayed
capXOff (Assignable)
Contains a numeric value that indicates the offset where the caption is displayed. This instance variable represents the number of pixels in the x direction (horizontally) from the left edge of the button where the caption will be displayed. If this instance variable is not supplied, the caption will be centered horizontally. This instance variable only affects applications running in graphic mode and is ignored in text mode.
capYOff Indicates the vertical offset where caption is displayed
capYOff (Assignable)
Contains a numeric value that indicates the offset where the caption is displayed. This instance variable represents the number of pixels in the y direction (vertically) from the top edge of the button where the caption will be displayed. If this instance variable is not supplied, the caption will be centered vertically. This instance variable only affects applications running in graphic mode and is ignored in text mode.
cargo User-definable variable
cargo (Assignable)
Contains a value of any type that is not used by the PushButton object. PushButton:cargo is provided as a user-definable slot allowing arbitrary information to be attached to a PushButton object and retrieved later.
col Indicates screen column where push button is displayed
col (Assignable)
Contains a numeric value that indicates the screen column where the push button is displayed.
colorSpec Indicates colors used by the push button's display() method
colorSpec (Assignable)
Contains a character string that indicates the color attributes that are used by the push button's display() method. The string must contain four color specifiers.
Note: The background colors of the PushButton Color Attributes are ignored in graphic mode.
PushButton Color Attributes
Position Applies To Default Value from
in colorSpec System Color Setting
1 The push button when it does not Unselected
have input focus
2 The push button when it has input Enhanced
focus and is not pressed
3 The push button when it has input Enhanced
focus and is pressed
4 The push button caption's Background
accelerator key
Note: The colors available to a DOS application are more limited than those for a Windows application. The only colors available to you here are listed in the drop-down list box of the Workbench Properties window for that item.
fBlock Code block evaluated at each input focus change
fBlock (Assignable)
Contains an optional code block that, when present, is evaluated each time the PushButton object receives or loses input focus. The code block takes no implicit arguments. Use the PushButton:hasFocus variable to determine if the push button is receiving or losing input focus. A value of true (.T.) indicates that it is receiving input focus; otherwise, a value of false (.F.) indicates that it is losing input focus.
This code block is included in the PushButton class to provide a method of indicating when an input focus change event has occurred. The name "fBlock" refers to focus block.
hasFocus Logical value indicating the input focus
hasFocus
Contains a logical value that indicates whether the PushButton object has input focus. PushButton:hasFocus contains true (.T.) if it has input focus; otherwise, it contains false (.F.).
message Character string describing the push button
message (Assignable)
Contains a character string that describes the push button. It is displayed on the screen's status bar line.
row Numeric value indicating row where push button is displayed
row (Assignable)
Contains a numeric value that indicates the screen row where the push button is displayed.
sBlock Code block evaluated at every state change
sBlock (Assignable)
Contains an optional code block that, when present, is evaluated each time the PushButton object's state changes. The code block takes no implicit arguments. Use the PushButton:buffer variable to determine if the push button is pressed or released. A value of true (.T.) indicates that it is being pressed; otherwise a value of false (.F.) indicates that it is being released.
This code block is included in the PushButton class to provide a method of indicating when a state change event has occurred. The name "sBlock" refers to state block.
sizeX Size of the button in pixels on the X-coordinate
sizeX (Assignable)
Contains a numeric value that indicates the size of the button in pixels on the X-coordinate (horizontally). This instance variable only affects applications running in graphic mode and is ignored in text mode.
sizeY Size of the button in pixels on the Y-coordinate
sizeY (Assignable)
Contains a numeric value that indicates the size of the button in pixels on the Y-coordinate (vertically). This instance variable only affects applications running in graphic mode and is ignored in text mode.
style Indicates characters used by push button's display() method
style (Assignable)
Contains a character string that indicates the delimiter characters that are used by the push button's display() method. The string must contain either zero, two or eight characters. The default is two characters. The first is the left delimiter. Its default value is the less than () character. The second character is the right delimiter. Its default value is the greater than () character.
When the string is empty the button has no delimiters.
When the string length is two, the button has left and right delimiters and occupies one row on the screen. The first character is the left delimiter. The second character is the right delimiter.
When the string length is eight, the button is contained within a box that occupies three rows on the screen. A PushButton object may only be either one or three lines in height.
Box.ch contains manifest constants for the PushButton:style value.
The default style for the PushButton class is "<>".
Note: The style instance variable is ignored in graphic mode.
typeOut Logical value false (.F.)
typeOut
Contains the logical value false (.F.). PushButton:typeOut never changes. It is not used by the PushButton object and is only provided for compatibility with the other GUI control classes.
Exported Methods
display() Shows a push button on the screen
oPushButton:display() → self
display() is a method of the PushButton class that is used for showing a push button on the screen. display() uses the values of the following instance variables to correctly show the push button in its current context, in addition to providing maximum flexibility in the manner a push button appears on the screen: buffer, caption, col, colorSpec, hasFocus, row, and style.
HitTest() Indicates position of mouse cursor relative to push button
oPushButton:hitTest(nMouseRow, nMouseCol)
→ nHitStatus
nMouseRow is a numeric value that indicates the current screen row position of the mouse cursor.
nMouseCol is a numeric value that indicates the current screen column position of the mouse cursor.
Returns a numeric value that indicates the relationship of the mouse cursor with the push button.
Applicable Hit Test Return Values
Value Constant Description
0 HTNOWHERE The mouse cursor is not within the region of
the screen that the push button occupies
-1 HTTOPLEFT The mouse cursor is on the top left corner of
the push button's border
-2 HTTOP The mouse cursor is on the push button's top
border
-3 HTTOPRIGHT The mouse cursor is on the top right corner of
the push button's border
-4 HTRIGHT The mouse cursor is on the push button's right
border
-5 HTBOTTOMRIGHT The mouse cursor is on the bottom right corner
of the push button's border
-6 HTBOTTOM The mouse cursor is on the push button's
bottom border
-7 HTBOTTOMLEFT The mouse cursor is on the bottom left corner
of the push button's border
-8 HTLEFT The mouse cursor is on the push button's left
border
-2049 HTCLIENT The mouse cursor is on the push button
Button.ch contains manifest constants for the PushButton:hitTest() return value.
HitTest() is a method of the PushButton class that is used for determining if the mouse cursor is within the region of the screen that the push button occupies.
killFocus() Takes input focus away from the PushButton object
oPushButton:killFocus() → self
killFocus() is a method of the PushButton class that is used for taking input focus away from a PushButton object. Upon receiving this message, the PushButton object redisplays itself and, if present, evaluates the code block within its fBlock variable.
This message is meaningful only when the PushButton object has input focus.
nInkeyValue is a numeric value that indicates the key that triggered the push button's activation. If passed, Select() waits for the key specified by nInkeyValue to be released before continuing.
Select() is a method of the PushButton class that is used for activating a push button. When activated, a push button performs several operations. First, Select() sets SELF:BUFFER to true (.T.). Then, it calls SELF:display() to show the button in its highlighted color. If nInkeyValue is passed, it waits for the key specified by nInkeyValue to be released. Then, if present, it evaluates its sBlock code block. Select() then calls SELF:display() to show the button in its selected color. A push button's state is typically changed when the space bar or enter key is pressed or the mouse's left button is pressed when its cursor is within the push button's screen region.
This message is meaningful only when the PushButton object has input focus.
setFocus() Gives input focus to the PushButton object
oPushButton:setFocus() → self
setFocus() is a method of the PushButton class that is used for giving focus to a PushButton object. Upon receiving this message, the PushButton object redisplays itself and, if present, evaluates the code block within its fBlock variable.
This message is meaningful only when the PushButton object does not have input focus.
Examples
■ This example creates an object which is placed at row 2 and
column 2 and has a caption of "Exit":
oBtn:PushButton(2,2,"Exit")
Create and initialize public memory variables and arrays
Syntax
PUBLIC <identifier> [[:= <initializer>], ... ]
Arguments
identifier is the name of a public variable or array to create. If the identifier is followed by square brackets ([ ]), it is created as an array. If the identifier is an array, the syntax for specifying the number of elements for each dimension can be array[nElements, nElements2,...] or array[nElements][nElements2].... The maximum number of elements per dimension is 4096. The maximum number of dimensions per array is limited only by available memory.
initializer is the optional assignment of a value to a new public variable. Array identifiers, however, cannot be given values with an initializer. An initializer for a public variable consists of the inline assignment operator (:=) followed by any valid CA-Clipper expression including a literal array. Except for arrays, if no initializer is specified, public variables are initialized to false (.F.). This is an exception to the general rule that uninitialized variables are NIL. With arrays, however, the initial value of each element is NIL.
A list of variables and arrays can be created and, optionally, initialized with one PUBLIC statement if each definition is separated by a comma.
Description
The PUBLIC statement creates variables and arrays visible to all procedures and user-defined functions in a program. Public variables exist for the duration of the program or until explicitly released with CLEAR ALL, CLEAR MEMORY, or RELEASE. Declaring private, local, or static variables or arrays with the same name as existing public variables temporarily hides those public variables until the overriding variables are released or are no longer visible. An attempt to create a public variable with the same name as an existing and visible private variable is simply ignored (see Notes below for an exception).
Attempting to specify a PUBLIC variable that conflicts with a previous FIELD, LOCAL, or STATIC declaration of the same name results in a fatal compiler error. This is true regardless of the scope of the declaration.
PUBLIC statements are executable statements and, therefore, must be specified within the body of a procedure or user-defined function definition. They also must follow all compile-time declarations, such as FIELD, LOCAL, MEMVAR, and STATIC.
The maximum number of public and private variables and arrays that can simultaneously exist in a single program is 2048.
For more information on variable declarations and scoping, refer to the Variables section in the "Basic Concepts" chapter of the Programming and Utilities Guide.
Notes
■ PUBLIC Clipper: To include CA-Clipper extensions in a program
and still allow the program to run under dBASE III PLUS, the special public variable, Clipper, is initialized to true (.T.) when created PUBLIC.
■ Public array name conflicts with existing private variables:
The statement, PUBLIC x[10], will not create the public array x if there is already a private or public variable x. It will, however, destroy the contents of the existing x, replacing it with a reference to a ten-element array.
Examples
■ This example creates two PUBLIC arrays and one PUBLIC
variable:
PUBLIC aArray1[10, 10], var2
PUBLIC aArray2[20][10]
■ The following PUBLIC statements create variables and
initialize them with values:
PUBLIC cString := Space(10), cColor := SetColor()
PUBLIC aArray := {1, 2, 3}, aArray2 := Array(12, 24)
exp list is a comma-separated list of expressions (of any data type other than array or block) to display to the console. If no argument is specified and QOut() is specified, a carriage return/line feed pair is displayed. If QQOut() is specified without arguments, nothing displays.
Returns
QOut() and QQOut() always return NIL.
Description
QOut() and QQOut() are console functions. These are the functional primitives that create the ? and ?? commands, respectively. Like the ? and ?? commands, they display the results of one or more expressions to the console. QOut() outputs carriage return and line feed characters before displaying the results of exp list. QQOut() displays the results of exp list at the current Row() and Col() position. When QOut() and QQOut() display to the console, Row() and Col() are updated. If SET PRINTER is ON, PRow() and PCol() are updated instead. If exp list is specified, both QOut() and QQOut() display a space between the results of each expression.
You can use QOut() and QQOut() for console display within an expression. This is particularly useful for blocks, iteration functions such as AEval() and dbEval(), and in a list of statements in the output pattern of a user-defined command definition.
Examples
■ This example uses QOut() with AEval() to list the contents of
a literal array to the console:
LOCAL aElements := { 1, 2, 3, 4, 5 }
AEval(aElements, { |element| QOut(element) })
QUIT and CANCEL both terminate program processing, close all open files, and return control to the operating system. Each of these commands can be used from anywhere in a program system. A RETURN executed at the highest level procedure or a BREAK, with no pending SEQUENCE, also QUITs the program.
Notes
■ Return code: When a CA-Clipper program terminates, the return
code is set to 1 if the process ends with a fatal error. If the process ends normally, the return code is set to zero or the last ErrorLevel() set in the program.
Examples
■ This example uses QUIT in a dialog box:
IF DialogYesNo(10, 10, "Quit to DOS", "BG+/B,B/W", 2)
QUIT
ENDIF
RETURN
Return an array of the available Replaceable Database Drivers (RDDs)
Syntax
rddList([<nRDDType>]) → aRDDList
Arguments
nRDDType is an integer that represents the type of the RDD you wish to list. The constants RDT_FULL and RDT_TRANSFER represent the two types of RDDs currently available.
RDDType Summary
Constant Value Meaning
RDT_FULL 1 Full RDD implementation
RDT_TRANSFER 2 Import/Export only driver
RDT_FULL identifies full-featured RDDs that have all the capabilities associated with an RDD.
RDT_TRANSFER identifies RDDs of limited capability. They can only transfer records between files. You cannot use these limited RDD drivers to open a file in a work area. The SDF and DELIM drivers are examples of this type of RDD. They are only used in the implementation of APPEND FROM and COPY TO with SDF or DELIMITED files.
Returns
rddList() returns a one-dimensional array of the RDD names registered with the application as nRDDType.
Description
rddList() is an RDD function that returns a one-dimensional array that lists the available RDDs.
If you do not supply nRDDType, all available RDDs regardless of type are returned.
Examples
■ In this example rddList() returns an array containing the
character strings, "DBF", "SDF", "DELIM", "DBFCDX", and "DBFNTX":
REQUEST DBFCDX
.
. < statements >
.
aRDDs := rddList()
// Returns {"DBF", SDF", "DELIM", "DBFCDX", "DBFNTX" }
■ In this example, rddList() returns an array containing the
character strings, "SDF" and "DELIM":
#include "rddsys.ch"
.
. < statements >
.
aImpExp := rddList( RDT TRANSFER )
Return the name of the RDD active in the current or specified work area
Syntax
rddName() → cRDDName
Returns
Returns a character string, cRDDName, the registered name of the active RDD in the current or specified work area.
Description
rddName() is an RDD function that returns a character string for the name of the active RDD, cRDDName, in the current or specified work area.
You can specify a work area other than the currently active work area by aliasing the function.
Examples
USE Customer VIA "DBFNTX" NEW
USE Sales VIA "DBFCDX" NEW
? rddName() // Returns: DBFCDX
? Customer->( rddName() ) // Returns: DBFNTX
? Sales->( rddName() ) // Returns: DBFCDX
cNewDefaultRDD is a character string, the name of the RDD that is to be made the new default RDD in the application.
Returns
rddSetDefault() returns a character string, cPreviousDefaultRDD, the name of the previous default driver. The default driver is the driver that CA-Clipper uses if you do not explicitly specify an RDD with the VIA clause of the USE command.
Description
rddSetDefault() is an RDD function that sets or returns the name of the previous default RDD driver and, optionally, sets the current driver to the new RDD driver specified by cNewDefaultRDD. If cNewDefaultDriver is not specified, the current default driver name is returned and continues to be the current default driver.
Radio buttons are typically presented in related groups and provide mutually exclusive responses to a condition where only one choice is appropriate. For example, a group of radio buttons might allow you to sort public variables either by name or by address.
Only one radio button can be on—when a new button is pressed, the previously selected button is turned off.
Methods link
Class Function
RadioButto() Create a new RadioButto object
RadioButto(nRow, nColumn, [cCaption])
→ oRadioButto
Arguments
nRow is a numeric value that indicates the screen row of the radio button.
nColumn is a numeric value that indicates the screen column of the radio button.
cCaption is an optional character string that contains a text string that describes the radio button on the screen. The default is an empty string.
Returns
Returns a RadioButto object when all of the required arguments are present; otherwise, RadioButto() returns NIL.
Exported Instance Variables
bitmaps An array of bitmap files to be displayed
bitmaps (Assignable)
Contains an array of exactly two elements. The first element of this array is the file name of the bitmap to be displayed when the radio button is selected. The second element of this array is the file name of the bitmap to be displayed when the radio button is not selected.
Drive and directory names are not allowed; the file name extension is required. A bitmap file can be stored as a file on disk or in a bitmap library. If stored as a file, the file must reside in the same directory as the application. If stored in a bitmap library, the library must reside in the same directory as the application and it also must have the same name as the application with a .BML extension.
CA-Clipper will search for the file name first and, if it is not found, search in the bitmap library second. If no file is found either on disk or in the library, no bitmap will be displayed.
If this instance variable is not used, and the application is running in graphic mode, the files RADIO_F.BMU and RADIO_E.BMU will be used for the selected bitmap and unselected bitmap, respectively.
This instance variable only affects applications running in graphic mode and is ignored in text mode.
buffer Logical value indicating whether a radio button is selected
buffer
Contains a logical value that indicates whether a radio button is selected or not. A value of true (.T.) indicates that it selected; otherwise, a value of false (.F.) indicates that it is not.
caption Character string describing the radio button on the screen
caption (Assignable)
Contains a character string that describes the radio button on the screen. When present, the & character specifies that the character immediately following it in the caption is the radio button's accelerator key. The accelerator key provides a quick and convenient mechanism for the user to move input focus from one radio button to another. The user performs the selection by pressing an accelerator key. The case of an accelerator key is ignored.
capCol Indicates column where radio button's caption is displayed
capCol (Assignable)
Contains a numeric value that indicates the screen column where the radio button's caption is displayed.
capRow Indicates column where radio button's caption is displayed
capRow (Assignable)
Contains a numeric value that indicates the screen row where the radio button's caption is displayed.
cargo User-definable variable
cargo (Assignable)
Contains a value of any type that is ignored by the RadioButto object. RadioButto:cargo is provided as a user-definable slot allowing arbitrary information to be attached to a RadioButto object and retrieved later.
col Indicates the column where the radio button is displayed
col (Assignable)
Contains a numeric value that indicates the screen column where the radio button is displayed.
colorSpec Indicates colors used by the radio button's display() method
colorSpec (Assignable)
Contains a character string that indicates the color attributes that are used by the radio button's display() method. The default is the system's current unselected and enhanced colors. The string must contain seven color specifiers.
Note: In graphic mode, colorSpec positions 1 through 4 have no affect and are ignored.
RadioButto Color Attributes
Position Applies To Default Value from
in colorSpec System Color Setting
1 A radio button when it is unselected Unselected
and does not have input focus
2 A radio button when it is selected Unselected
and does not have input focus
3 A radio button when it is unselected Enhanced
and has input focus
4 A radio button when it is selected and Enhanced
has input focus
5 A radio button's caption Standard
6 A radio button caption's accelerator Standard
key when it does not have input focus
7 A radio button caption's accelerator Background
key when it has input focus
Note: The colors available to a DOS application are more limited than those for a Windows application. The only colors available to you here are listed in the drop-down list box of the Workbench Properties window for that item.
fBlock Code block evaluated at each input focus change
fBlock (Assignable)
Contains an optional code block that, when present, is evaluated each time the RadioButto object receives or loses input focus. The code block takes no implicit arguments. Use the RadioButto:hasFocus instance variable to determine if the radio button is receiving or losing input focus. A value of true (.T.) indicates that it is receiving input focus; otherwise, a value of false (.F.) indicates that it is losing input focus.
This code block is included in the RadioButto class to provide a method of indicating when an input focus change event has occurred. The name "fBlock" refers to focus block.
hasFocus Logical value indicating the input focus
hasFocus
Contains a logical value that indicates whether the RadioButto object has input focus. RadioButto:hasFocus contains true (.T.) if it has input focus; otherwise, it contains false (.F.) .
row Indicates the row where the radio button is displayed
row (Assignable)
Contains a numeric value that indicates the screen row where the radio button is displayed.
sBlock Code block evaluated at every state change
sBlock (Assignable)
Contains an optional code block that, when present, is evaluated each time the RadioButto object's state changes. The code block takes no implicit arguments. Use the RadioButto:buffer instance variable to determine whether the radio button is being selected or unselected. A value of true (.T.) indicates that it is being selected; otherwise, a value of false (.F.) indicates that it is being unselected.
This code block is included in the RadioButto class to provide a method of indicating when a state change event has occurred. The name "sBlock" refers to state block.
style Indicates characters used by radio button's display() method
style (Assignable)
Contains a character string that indicates the characters that are used by the radio button's display() method. The string must contain four characters. The first is the left delimiter. Its default value is the left parenthesis ( ( ) character. The second is the selected indicator. Its default value is the asterisk (*) character. The third is the unselected indicator. Its default is the space ( " " ) character. The fourth character is the right delimiter. Its default value is the right parenthesis ( ) ) character.
Note: In graphic mode, the style instance variable is ignored.
Exported Methods
display() Shows a radio button and its caption on the screen
oRadioButto:display() → self
display() is a method of the RadioButto class that is used for showing a radio button and its caption on the screen. display() uses the values of the following instance variables to correctly show the radio button in its current context in addition to providing maximum flexibility in the manner a radio button appears on the screen: buffer, caption, capCol, capRow, col, colorSpec, hasFocus, row, and style.
HitTest() Indicates position of mouse cursor relative to radio button
oRadioButto:hitTest(nMouseRow, nMouseCol)
→ nHitStatus
nMouseRow is a numeric value that indicates the current screen row position of the mouse cursor.
nMouseCol is a numeric value that indicates the current screen column position of the mouse cursor.
Returns a numeric value that indicates the relationship of the mouse cursor with the radio button.
Applicable Hit Test Return Values
Value Constant Description
0 HTNOWHERE The mouse cursor is not within the region of the
screen that the radio button occupies
-1025 HTCAPTION The mouse cursor is on the radio button's caption
-2049 HTCLIENT The mouse cursor is on the radio button
Button.ch contains manifest constants for the RadioButto:hitTest() return value.
HitTest() is a method of the RadioButto class that is used for determining if the mouse cursor is within the region of the screen that the radio button occupies.
HitTest() returns a numeric value in order to maintain an appropriate level of symmetry with the HitTest() methods contained within the other data input control classes.
isAccel() Determines if a key press is interpreted as a user request
oRadioButto:isAccel(nInkeyValue)
→ lHotKeyStatus
nInkeyValue is a numeric value that indicates the inkey value to check.
Returns a logical value that indicates whether the value specified by nInkeyValue should be treated as a hot key. A value of true (.T.) indicates that the key should be treated as a hot key; otherwise, a value of false (.F.) indicates that it should not.
isAccel() is a method of the RadioButto class that is used for determining whether a key press should be interpreted as a user request to select a radio button.
killFocus() Takes input focus away from the RadioButto object
oRadioButto:killFocus() → self
killFocus() is a method of the RadioButto class that is used for taking input focus away from a RadioButto object. Upon receiving this message, the RadioButto object redisplays itself and, if present, evaluates the code block within its fBlock instance variable.
This message is meaningful only when the RadioButto object has input focus.
lNewState is a logical value that indicates whether the radio button should be selected or not. Set to true (.T.) to select the button or false (.F.) to deselect the button. If omitted, the radio button state will toggle to its opposing state.
Select() is a method of the RadioButto class that is used for changing the state of a radio button. Its state is typically changed when the space bar or one of the arrow keys is pressed or the mouse's left button is pressed when its cursor is within the radio button's screen region.
This message is meaningful only when the RadioButto object has input focus, or when the radio button is a member of a Group object that has input focus.
setFocus() Gives input focus to the RadioButto object
oRadioButto:setFocus() → self
setFocus() is a method of the RadioButto class that is used for giving focus to a RadioButto object. Upon receiving this message, the RadioButto object redisplays itself and, if present, evaluates the code block within its fBlock instance variable.
This message is meaningful only when the RadioButto object does not have input focus.
Examples
■ This example creates two radio buttons, one with a caption of
"Commands" and the other "Macros," and groups them together using the
RadioGroup class:
oRadio1:RadioButto(2,2,"Commands")
oRadio2:RadioButto(3,2,"Macros")
oRadiogroup:RadioGroup(2,2,3,9)
The RadioGroup class provides a convenient mechanism for manipulating radio buttons.
Methods link
Class Function
RadioGroup() Create a new RadioGroup object
RadioGroup(nTop, nLeft, nBottom, nRight)
→ oRadioGroup
Arguments
nTop is a numeric value that indicates the top screen row of the radio group.
nLeft is a numeric value that indicates the left screen column of the radio group.
nBottom is a numeric value that indicates the bottom screen row of the radio group.
nRight is a numeric value that indicates the right screen column of the radio group.
Returns
Returns a RadioGroup object when all of the required arguments are present; otherwise, RadioGroup() returns NIL.
Exported Instance Variables
bottom Numeric value indicating the bottommost screen row
bottom (Assignable)
Contains a numeric value that indicates the bottommost screen row where the radio group is displayed.
buffer Numeric value indicating the position in the radio group
buffer (Assignable)
Contains a numeric value that indicates the position in the radio group of the selected radio button.
capCol Indicates column where radio group's caption is displayed
capCol (Assignable)
Contains a numeric value that indicates the screen column where the radio group's caption is displayed.
capRow Indicates row where the radio group's caption is displayed
capRow (Assignable)
Contains a numeric value that indicates the screen row where the radio group's caption is displayed.
caption Character string describing the radio group on the screen
caption (Assignable)
Contains a character string that concisely describes the radio group on the screen.
When present, the & character specifies that the character immediately following it in the caption is the radio group's accelerator key. The accelerator key provides a quick and convenient mechanism for the user to move input focus from one data input control to a radio group. The user performs the selection by pressing the Alt key in combination with an accelerator key. The case of an accelerator key is ignored.
cargo User-definable variable
cargo (Assignable)
Contains a value of any type that is ignored by the RadioGroup object. RadioGroup:cargo is provided as a user-definable slot allowing arbitrary information to be attached to a RadioGroup object and retrieved later.
coldBox Characters to use when drawing a box around a radio group
coldBox (Assignable)
Contains an optional string that specifies the characters to use when drawing a box around the radio group when it does not have input focus. Its default value is a single-line box.
Box.ch contains manifest constants for the RadioGroup:coldBox value.
colorSpec Indicates colors used by the radio group's display() method
colorSpec (Assignable)
Contains a character string that indicates the color attributes that are used by the radio group's display() method. The string must contain three color specifiers.
RadioGroup Color Attributes
Position Applies To Default Value from
in colorSpec System Color Setting
1 The radio group's border Border
2 The radio group's caption Standard
3 The radio group caption's Background
accelerator key
Note: The colors available to a DOS application are more limited than those for a Windows application. The only colors available to you here are listed in the drop-down list box of the Workbench Properties window for that item.
fBlock Code block evaluated at each input focus change
fBlock (Assignable)
Contains an optional code block that, when present, is evaluated each time the RadioGroup object receives or loses input focus. The code block takes no implicit arguments. Use the RadioGroup:hasFocus instance variable to determine if the radio group is receiving or losing input focus. A value of true (.T.) indicates that it is receiving input focus; otherwise, a value of false (.F.) indicates that it is losing input focus.
This code block is included in the RadioGroup class to provide a method of indicating when an input focus change event has occurred. The name "fBlock" refers to focus block.
hasFocus Logical value indicating the input focus
hasFocus
Contains a logical value that indicates whether the RadioGroup object has input focus. It should contain true (.T.) when it has input focus; otherwise, it should contain false (.F.).
hotBox Specifies characters to use when drawing a radio group's box
hotBox (Assignable)
Contains an optional string that specifies the characters to use when drawing a box around the radio group when it has input focus. Its default value is a double-line box.
Box.ch contains manifest constants for the RadioGroup:hotBox value.
itemCount Indicates total number of radio buttons in the radio group
itemCount (Assignable)
Contains a numeric value that indicates the total number of radio buttons in the RadioGroup object.
left Indicates leftmost column where the radio group is displayed
left (Assignable)
Contains a numeric value that indicates the leftmost screen column where the radio group is displayed.
message Character string that is the radio group's description
message (Assignable)
Contains a character string that is the radio group's description that is displayed on the screen's status bar line.
right Indicates rightmost column where radio group is displayed
right (Assignable)
Contains a numeric value that indicates the rightmost screen column where the radio group is displayed.
top Indicates the topmost row where the radio group is displayed
top (Assignable)
Contains a numeric value that indicates the topmost screen row where the radio group is displayed.
typeOut Logical value indicating whether group contains any buttons
typeOut (Assignable)
Contains a logical value that indicates whether the group contains any buttons. A value of true (.T.) indicates the group contains selectable buttons; a false (.F.) value indicates that the group is empty.
Exported Methods
addItem() Appends a new radio button to a radio group
oRadioGroup:addItem(oRadioButto) → self
oRadioButto is the radio button object to be added.
addItem() is a method of the RadioGroup class that is used for appending a new radio button to a radio group.
delItem() Removes a radio button from a radio group
oRadioGroup:delItem(nPosition>) → self
nPosition is a numeric value that indicates the position in the radio group of the radio button to be deleted.
delItem() is a method of the RadioGroup class that is used for removing a radio button from a radio group.
display() Shows its radio buttons on the screen
oRadioGroup:display() → self
display() is a method of the RadioGroup class used for showing its radio buttons on the screen. display() accomplishes this by calling the display() method of each of the radio buttons in its group.
getAccel() Determines if a key press is interpreted as a user request
oRadioGroup:getAccel(nInkeyValue) → nPosition
nInkeyValue is a numeric value that indicates the inkey value to check.
Returns a numeric value that indicates the position in the radio group of the first item whose accelerator key matches that which is specified by nInkeyValue.
getAccel() is a method of the RadioGroup class that is used for determining whether a key press should be interpreted as a user request to select a particular radio button. getAccel() accomplishes this by calling the getAccel() method of each of the radio buttons in its group.
getItem() Retrieves a radio button from a radio group
oRadioGroup:getItem(nPosition) → oRadioButto
nPosition is a numeric value that indicates the position in the list of the item that is being retrieved.
Returns the RadioButto object specified by nPosition.
getItem() is a method of the RadioGroup class that is used for retrieving a radio button from a radio group.
HitTest() Indicates position of mouse cursor relative to radio group
oRadioGroup:hitTest(nMouseRow, nMouseCol)
→ nHitStatus
nMouseRow is a numeric value that indicates the current screen row position of the mouse cursor.
nMouseCol is a numeric value that indicates the current screen column position of the mouse cursor.
Returns a numeric value that indicates the relationship of the mouse cursor with the radio group.
Applicable Hit Test Return Values
Value Constant Description
> 0 Not Applicable The position in the radio group of the radio
button whose region the mouse is within
0 HTNOWHERE The mouse cursor is not within the region of
the screen that the radio group occupies
-1 HTTOPLEFT The mouse cursor is on the radio group's
border
-2 HTTOP The mouse cursor is on the radio group's top
border
-3 HTTOPRIGHT The mouse cursor is on the top right corner of
the radio group's border
-4 HTRIGHT The mouse cursor is on the radio group's right
border
-5 HTBOTTOMRIGHT The mouse cursor is on the bottom right corner
of the radio group's border
-6 HTBOTTOM The mouse cursor is on the radio group's bottom
border
-7 HTBOTTOMLEFT The mouse cursor is on the bottom left corner
of the radio group's border
-8 HTLEFT The mouse cursor is on the radio group's left
border
-2049 HTCLIENT The mouse cursor is within the radio group's
screen region but not on a radio button
Button.ch contains manifest constants for the RadioGroup:hitTest() return value.
HitTest() is a method of the RadioGroup class that is used for determining if the mouse cursor is within the region of the screen that any of the RadioButto objects contained within the radio group occupies. HitTest() accomplishes this by calling the HitTest() method of each of the radio buttons in its group.
insItem() Inserts a new radio button into a radio group
oRadioGroup:insItem(nPosition, oRadioButto)
→ self
nPosition is a numeric value that indicates the position at which the new item is inserted.
oRadioButto is the RadioButto object to be inserted.
insItem() is a method of the RadioGroup class that is used for inserting a new radio button into a radio group.
killFocus() Takes input focus away from the RadioGroup object
oRadioGroup:killFocus() → self
killFocus() is a method of the RadioGroup class that is used for taking input focus away from a RadioGroup object. Upon receiving this message, the RadioGroup object redisplays itself and, if present, evaluates the code block within its fBlock instance variable.
This message is meaningful only when the RadioGroup object has input focus.
nextItem() Changes radio button from current item to the following one
oRadioGroup:nextItem() → self
nextItem() is a method of the RadioGroup class that is used for changing the selected radio button from the current item to the one immediately following it.
This message is meaningful only when the RadioGroup object has input focus.
prevItem() Changes radio button from current item to the previous one
oRadioGroup:prevItem() → self
prevItem() is a method of the RadioGroup class that is used for changing the selected item from the current radio button to the one immediately before it.
This message is meaningful only when the RadioGroup object has input focus.
Select() Changes the selected radio button in a radio group
oRadioGroup:select(nPosition) → self
nPosition is a numeric value that indicates the position in the list of the radio button to be selected.
Select() is a method of the RadioGroup class that is used for changing the selected radio button in a radio group. Its state is typically changed when one of the arrow keys is pressed or the mouse's left button is pressed when its cursor is within one of the radio button's screen region.
This message is meaningful only when the RadioGroup object has input focus.
SetColor() Sets the color attributes of all radio buttons in a group
oRadioGroup:setColor([cColorString]) → self
cColorString is a character string that indicates the color attributes that are used by the radio button's display() method. The string must contain seven color specifiers.
RadioButto Color Attributes
Position Applies To Default Value from
in colorSpec System Color Setting
1 A radio button when it is unselected Unselected
and does not have input focus
2 A radio button when it is selected and Unselected
does not have input focus
3 A radio button when it is unselected Enhanced
and has input focus
4 A radio button when it is selected and Enhanced
has input focus
5 A radio button's caption Standard
6 A radio button caption's accelerator Standard
key when it does not have input focus
7 A radio button caption's accelerator Background
key when it has input focus
SetColor() is a method of the RadioGroup class that is used for uniformly setting the color attributes of all the radio buttons in its group. SetColor() accomplishes this by setting the colorSpec instance variable of each of the radio buttons in its group to the value specified by cColorString.
setFocus() Gives input focus to the RadioGroup object
oRadioGroup:setFocus() → self
setFocus() is a method of the RadioGroup class that is used for giving focus to a RadioGroup object. Upon receiving this message, the RadioGroup object redisplays itself and, if present, evaluates the code block within its fBlock instance variable.
This message is meaningful only when the RadioGroup object does not have input focus.
setStyle() Sets the style attribute of all radio buttons in a group
oRadioGroup:setStyle([cStyle]) → self
cStyle is a character string that indicates the characters that are used by the radio button's display() method. The string must contain four characters. The first is the left delimiter. The second is the selected indicator. The third is the unselected indicator. The fourth character is the right delimiter.
setStyle() is a method of the RadioGroup class that is used for uniformly setting the Style attribute of all the radio buttons in its group. setStyle() accomplishes this by setting the Style of each of the radio buttons in its group to the value specified by cStyle.
Examples
■ This example creates a group of radio buttons, one with a
caption of "Commands" and the other "Macros":
oRadio1:RadioButto(2,2,"Commands")
oRadio2:RadioButto(3,2,"Macros")
oRadiogroup:RadioGroup(2,2,3,9)
Return the position of the last occurrence of a substring
Syntax
RAt(<cSearch>, <cTarget>) → nPosition
Arguments
cSearch is the character string to be located.
cTarget is the character string to be searched.
Returns
RAt() returns the position of cSearch within cTarget as an integer numeric value. If cSearch is not found, RAt() returns zero.
Description
RAt() is a character function that returns the position of the last occurrence of a character substring within another character string. It does this by searching the target string from the right. RAt() is like the At() function, which returns the position of the first occurrence of a substring within another string. RAt() is also like the $ operator, which determines whether a substring is contained within a string.
Both the RAt() and At() functions are used with SubStr(), Left(), and Right() to extract substrings.
Examples
■ This example uses RAt() to create a user-defined function,
FilePath(), that extracts the path from a file specification. If the
path is unspecified, FilePath() returns a null string (""):
? FilePath("C:\DBF\Sales.dbf") // Result: C:\DBF\
FUNCTION FilePath( cFile )
LOCAL nPos, cFilePath
IF (nPos := RAt("\", cFile)) != 0
cFilePath = SubStr(cFile, 1, nPos)
ELSE
cFilePath = ""
ENDIF
RETURN cFilePath
lToggle toggles the use of Up arrow and Down arrow as READ exit keys. Specifying true (.T.) enables them as exit keys, and false (.F.) disables them.
Returns
ReadExit() returns the current setting as a logical value.
Description
ReadExit() is an environment function that reports the current state of Up arrow and Down arrow as keys the user can press to exit a READ from the first or last Get object in a GetList. If the optional lToggle argument is specified, Up arrow and Down arrow are either enabled or disabled as READ exit keys. At program startup, Up arrow and Down arrow are not enabled as READ exit keys. Normally, READ exit keys include only Pgup, Pgdn, Esc, or Return from the last GET.
Examples
■ This example shows ReadExit() enabling Up arrow and Down arrow
exit keys before a READ then resetting them after the READ
terminates:
cMyvar = Space(10)
lLastExit = ReadExit(.T.) // Result: Turn on exit keys
//
@ 10, 10 SAY "Enter: " GET cMyvar
READ
ReadExit(lLastExit) // Result: Restore previous setting
Return and optionally, set the code block that implements a format (.fmt) file
Syntax
ReadFormat([<bFormat>]) → bCurrentFormat
Arguments
bFormat is the name of the code block, if any, to use for implementing a format file. If no argument is specified, the function simply returns the current code block without setting a new one.
Returns
ReadFormat() returns the current format file as a code block. If no format file has been set, ReadFormat() returns NIL.
Description
ReadFormat() is a Get system function that accesses the current format file in its internal code block representation. It lets you manipulate the format file code block from outside of the Get system's source code.
To set a format file, use SET FORMAT (see the SET FORMAT entry ) or ReadFormat().
ReadFormat() is intended primarily for creating new READ layers. The code block that ReadFormat() returns, when evaluated, executes the code that is in the format file from which it was created.
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, source file is Getsys.prg.
Toggle the current insert mode for READ and MemoEdit()
Syntax
ReadInsert([<lToggle>]) → lCurrentMode
Arguments
lToggle toggles the insert mode on or off. True (.T.) turns insert on, while false (.F.) turns insert off. The default is false (.F.) or the last user-selected mode in READ or MemoEdit().
Returns
ReadInsert() returns the current insert mode state as a logical value.
Description
ReadInsert() is an environment function that reports the current state of the insert mode for READ and MemoEdit() and, optionally, sets the insert mode on or off depending on the value of lToggle. When ReadInsert() returns false (.F.) and the user enters characters into a Get object's buffer during a READ or a MemoEdit(), characters are overwritten. When ReadInsert() returns true (.T.), entered characters are inserted instead. The insert mode is a global setting belonging to the system and not to any specific object.
You can execute ReadInsert() prior to or during a READ or MemoEdit(). If used with READ, ReadInsert() can be invoked within a WHEN or VALID clause of @...GET or within a SET KEY procedure. If used with MemoEdit(), it can be invoked with the user function as well as a SET KEY procedure.
Examples
■ This example sets the insert mode prior to entering MemoEdit()
and resets the mode when MemoEdit() terminates:
USE Sales NEW
// Turn on insert mode
lInsMode = ReadInsert(.T.)
Sales->Notes := MemoEdit(Sales->Notes)
//
// Restore previous insert mode
ReadInsert(lInsMode)
ReadKey() returns a code representing the key pressed to exit a READ. In CA-Clipper, the following keys are the standard READ exit keys and their ReadKey() return codes:
ReadKey() Return Codes
Exit Key Return Code
Up arrow 5
Down arrow 2
PgUp 6
PgDn 7
Ctrl+PgUp 31
Ctrl+PgDn 30
Esc 12
Ctrl+End, Ctrl+W 14
Type past end 15
Return 15
Description
ReadKey() is a keyboard function that emulates the ReadKey() function in dBASE III PLUS. Its purpose is to determine what key the user pressed to terminate a READ. If Updated() is true (.T.), ReadKey() returns the code plus 256. Up arrow and Down arrow exit a READ only if ReadExit() returns true (.T.). The default value is false (.F.). To provide complete compatibility for these keys, execute a READEXIT (.T.) at the beginning of your main procedure.
ReadKey() is supplied as a compatibility function and, therefore, its use is strongly discouraged. It is superseded entirely by LastKey() which determines the last keystroke fetched from the keyboard buffer. If the keystroke was a READ exit key, LastKey() will return the Inkey() code for that key. To determine whether any Get object's buffer was modified during a READ, it is superseded by the Updated() function.
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/READKEY.PRG
Return, and optionally set, whether the current READ should be exited
Syntax
ReadKill([<lKillRead>]) → lCurrentSetting
Arguments
lKillRead sets the ReadKill() flag. A value of true (.T.) indicates that the current read should be terminated, and a value of false (.F.) indicates that it should not.
Returns
ReadKill() returns the current setting as a logical value.
Description
ReadKill() is a Get system function that lets you control whether or not to terminate the current READ.
Unless directly manipulated, ReadKill() returns true (.T.) after you issue a CLEAR GETS (see the CLEAR GETS entry ) for the current READ; otherwise, it returns false (.F.).
By accessing the function directly, however, you can control the ReadKill() flag with its function argument and use it to create new READ layers.
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, source file is Getsys.prg.
aGetList is an array containing a list of Get objects to edit.
nGet is an optional numeric value that indicates which Get object within aGetList should initially receive input focus.
oMenu is an optional Topbarmenu object that, when supplied, permits menu selection during data entry.
nMsgRow, nMsgLeft, and nMsgRight specify the row, left, and right margins where the Get object messages appear on the screen.
cMsgColor defines the color setting of the message area. It consists of a single foreground/background color pair.
Returns
ReadModal() returns true (.T.) when GetList is updated, false (.F.) when it is not.
Description
ReadModal() is a user interface function that implements the full-screen editing mode for GETs, and is part of the open architecture Get system of CA-Clipper. ReadModal() is like the READ command, but takes a GetList array as an argument and does not reinitialize the GetList array when it terminates. Because of this, you can maintain multiple lists of Get objects and activate them any time in a program's execution as long as the array to activate is visible.
In order to retain compatibility with previous versions of CA-Clipper, the GET system in CA-Clipper is implemented using a public array called GetList. Each time an @...GET command executes, it creates a Get object and adds to the currently visible GetList array. The standard READ command is preprocessed into a call to ReadModal() using the GetList array as its argument. If the SAVE clause is not specified, the variable GetList is assigned an empty array after the ReadModal() function terminates.
Some of the functions in the Getsys.prg have been made public so that they can be used when implementing customized GET readers. These functions are listed in the table below.
Get System functions
Function Description
GetActive() Return the currently active Get object
GetApplyKey() Apply a key to a Get object from within a GET reader
GetDoSetKey() Process SET KEY during GET editing
GetPostValidate() Postvalidate the current Get object
GetPreValidate() Prevalidate a Get object
GetReader() Execute standard READ behavior for a Get object
ReadFormat() Return and, optionally, set the code block that
implements a format (.fmt) file
ReadKill() Return and, optionally, set whether the current Read
should be exited
ReadUpdated() Return and, optionally, set whether a GET has
changed during a Read
For reference information on the Get objects and functions listed above, refer to the "Get System" chapter in the Programming and Utilities Guide.
For more information on the supported keys in the default ReadModal() function, refer to the READ command reference in this chapter.
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, source file is SOURCE/SYS/GETSYS.PRG
Determine whether any GET variables changed during a READ and optionally change the ReadUpdated() flag
Syntax
ReadUpdated([<lChanged>]) → lCurrentSetting
Arguments
lChanged sets the ReadUpdated() flag. A value of true (.T.) indicates that data has changed, and a value of false (.F.) indicates that no change has occurred.
Returns
ReadUpdated() returns the current setting as a logical value.
Description
ReadUpdated() is a Get system function intended primarily for creating new READ Layers. It is identical in functionality to Updated() (see the Updated() entry ), except that it allows the Updated() flag to be set.
ReadUpdated() enables you to manipulate the Updated() flag from outside of the Get system's source code.
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, source file is Getsys.prg.
ReadVar() returns the name of the variable associated with the current Get object or the variable being assigned by the current MENU TO command as an uppercase character string.
Description
ReadVar() is an environment function that primarily implements context- sensitive help for Get objects and lightbar menus. ReadVar() only works during a READ or MENU TO command. If used during any other wait states, such as ACCEPT, INPUT, WAIT, AChoice(), dbEdit(), or MemoEdit(), it returns a null string (""). Access it within a SET KEY procedure, or within a user-defined function invoked from a WHEN or VALID clause of a Get object.
Examples
■ This example implements a simple help system for Get objects
using a database file to store the help text. When the user presses
F1, the help database file is searched using ReadVar() as the key
value. If there is help text available, it is displayed in a window:
#include "Inkey.ch"
//
SET KEY K_F1 TO HelpLookup
cString = Space(10)
@ 5, 5 SAY "Enter:" GET cString
READ
RETURN
FUNCTION HelpLookup
USE Help INDEX Help NEW
SEEK ReadVar()
IF Found()
DisplayHelp(Help->Topic)
ELSE
DisplayHelp("No help for " + ReadVar())
ENDIF
CLOSE Help
RETURN NIL
FUNCTION DisplayHelp( cTopic )
LOCAL cScreen := SaveScreen(5,5,15,70),;
cColor := SetColor("BG+/B")
//
SET CURSOR OFF
@ 5, 5 CLEAR TO 15, 70
@ 5, 5 TO 15, 70 DOUBLE
@ 5, 30 SAY " Help for " + ReadVar() + " "
MemoEdit(cTopic, 6, 7, 14, 68, .F.)
//
RestScreen(5, 5, 15, 70, cScreen)
SetColor(cColor)
SET CURSOR ON
//
RETURN NIL
Determine the number of records in the current database (.dbf) file
Syntax
RecCount()* | LastRec() → nRecords
Returns
RecCount() returns the number of physical records in the current database file as an integer numeric value. Filtering commands such as SET FILTER or SET DELETED have no affect on the return value. RecCount() returns zero if there is no database file open in the current work area.
Description
RecCount() is a database function that is a synonym for LastRec(). By default, RecCount() operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression (see example below). Note that RecCount() is a compatibility function. LastRec() should be used in its place.
Examples
■ This example illustrates the relationship between COUNT and
RecCount():
USE Sales NEW
? RecCount() // Result: 84
//
SET FILTER TO Salesman = "1001"
COUNT TO nRecords
? nRecords // Result: 14
? RecCount() // Result: 84
■ This example uses an aliased expression to access the number
of records in an unselected work area:
USE Sales NEW
USE Customer NEW
? RecCount(), Sales->(RecCount())
Return the identity at the position of the record pointer
Syntax
RecNo() → Identity
Returns
RecNo() returns the identity found at the position of the record pointer.
Description
RecNo() is a database function that returns the identity found at the current position of the record pointer. Identity is a unique value guaranteed by the structure of the data file to reference a specific record of a data file. The data file need not be a traditional Xbase file. Therefore, unlike earlier versions of CA-Clipper, the value returned need not be a numeric data type.
Under all RDDs, RecNo() returns the value at the position of the record pointer; the data type and other characteristics of this value are determined by the content of the accessed data and the RDD active in the current work area. In an Xbase database this value is the record number.
Examples
USE Sales VIA "DBFNTX"
.
. < statements >
.
dbGoTop()
RecNo() // Returns 1
Determine the record length of a database (.dbf) file
Syntax
RecSize() → nBytes
Returns
RecSize() returns, as a numeric value, the record length in bytes of the database file open in the current work area. RecSize() returns zero if no database file is open.
Description
RecSize() is a database function that determines the length of a record by summing the lengths of each field then adding one for the Deleted() status flag. When this value is multiplied by LastRec(), the product is the amount of space occupied by the file's records.
RecSize() is useful in programs that perform automatic file backup. When used in conjunction with DiskSpace(), the RecSize() function can assist in ensuring that sufficient free space exists on the disk before a file is stored.
By default, RecSize() operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression (see example below).
Examples
■ The following user-defined function, DbfSize(), uses RecSize()
to calculate the size of the current database file:
FUNCTION DbfSize
RETURN ((RecSize() * LastRec()) + Header() + 1)
■ This example illustrates the use of RecSize() to determine the
record length of database files open in unselected work areas:
USE Customer NEW
USE Sales NEW
//
? RecSize(), Customer->(RecSize())
? DbfSize(), Customer->(DbfSize())
Return a string repeated a specified number of times
Syntax
Replicate(<cString>, <nCount>) → cRepeatedString
Arguments
cString is the character string to be repeated.
nCount is the number of times to repeat cString.
Returns
Replicate() returns a character string up to a maximum of 65,535 (64K) bytes in length. Specifying a zero as the nCount argument returns a null string ("").
Description
Replicate() is a character function that repeatedly displays, prints, or stuffs the keyboard with one or more characters. Replicate() is like the Space() function, which returns a specified number of space characters.
Examples
■ These examples demonstrate Replicate() repeating strings:
? Replicate("*", 5) // Result: *****
? Replicate("Hi ", 2) // Result: Hi Hi
? Replicate(Chr(42), 5) // Result: *****
■ This example uses Replicate() to stuff the keyboard with
several Down arrow keys:
#include "Inkey.ch"
KEYBOARD REPLICATE(Chr(K_DOWN), 25)
nTop, nLeft, nBottom, and nRight define the coordinates of the screen information contained in cScreen. If cScreen was saved without coordinates to preserve the entire screen, no screen coordinates are necessary with RestScreen().
cScreen is a character string containing the saved screen region.
Returns
RestScreen() always returns NIL.
Description
RestScreen() is a screen function that redisplays a screen region saved with SaveScreen(). The target screen location may be the same as or different from the original location when the screen region was saved. If you specify a new screen location, the new screen region must be the same size or you will get ambiguous results. To use RestScreen() to restore screen regions saved with SAVE SCREEN, specify the region coordinates as 0, 0, MaxRow(), MaxCol().
Warning! SAVE SCREEN, RESTORE SCREEN, SaveScreen(), and RestScreen() are supported when using the default (IBM PC memory mapped) screen driver. Other screen drivers may not support saving and restoring screens.
Examples
■ This example demonstrates RestScreen() as part of a general
purpose pop-up menu function, PopMenu():
? PopMenu({1, 1, 3, 10, {"ItemOne", "ItemTwo"}, ;
"BG+/B"})
FUNCTION PopMenu( aList )
LOCAL cScreen, nChoice, cOldColor := ;
SetColor(aList[6])
cScreen := SaveScreen(aList[1], aList[2],;
aList[3], aList[4])
@ aList[1], aList[2], TO aList[3], aList[4] DOUBLE
nChoice := AChoice(++aList[1], ++aList[2],;
--aList[3], --aList[4], aList[5])
SetColor(cOldColor)
RestScreen(--aList[1], --aList[2], ++aList[3],;
++aList[4], cScreen)
RETURN nChoice
Activate full-screen editing mode using Get objects
Syntax
READ [SAVE] [MENU <oMenu>] [MSG AT <nRow>, <nLeft>,
<nRight>] [MSG COLOR <cColorString>]
Arguments
SAVE retains the contents of the current GetList after the READ terminates. Later, you can edit the same Get objects by issuing another READ. If not specified, the current GetList is assigned an empty array deleting all of the previous Get objects when the READ terminates.
MENUoMenu specifies an optional Topbarmenu object that, when supplied, permits menu selection during data entry.
MSG ATnMsgRow, nMsgLeft, nMsgRight specify the row, left, and right margins where the Get object messages appear on the screen. If omitted, messages will not appear.
MSG COLORcMsgColor defines the color setting of the message area. It consists of a single foreground/background color pair.
Description
READ executes a full-screen editing mode using all Get objects created and added to the current GetList since the most recent CLEAR, CLEAR GETS, CLEAR ALL or READ commands. If there is a format procedure active, READ executes that procedure before entering the full-screen editing mode.
Within a READ, the user can edit the buffer of each Get object as well as move from one Get object to another. Before the user can enter a Get object, control passes to the associated WHENlPreCondition if one has been assigned to that Get object. If lPreCondition returns true (.T.), the user is allowed to edit the buffer of the Get object. Otherwise, control passes to the next Get object in the GetList. Within a GET buffer, the user can edit using the full complement of editing and navigation keys. See the tables below.
When the user presses a GET exit key, control passes to the associated RANGE or VALID postcondition if one has been specified. If either condition returns true (.T.), editing of the Get object is terminated and control passes to the next Get object. Otherwise, control remains within the current Get object until a valid value is entered or the user presses the Esc key.
When the user successfully enters a value into a Get object, the associated variable is assigned the value of the Get object's buffer.
The following tables list active keys within a READ:
READ Navigation Keys
Key Action
Left arrow, Ctrl+S Character left. Does not move cursor to
previous GET.
Right arrow, Ctrl+D Character right. Does not move cursor to
next GET.
Ctrl+Left arrow, Ctrl+A Word left.
Ctrl+Right arrow, Ctrl+F Word right.
Up arrow, Shift+Tab, Ctrl+E Previous GET.
Down arrow, Tab, Ctrl+X, Return, Ctrl+M Next GET.
Home First character of GET.
End Last character of GET.
Ctrl+Home Beginning of first GET.
READ Editing Keys
Key Action
Del, Ctrl+G Delete character at cursor position
Backspace, Ctrl+H Destructive backspace
Ctrl+T Delete word right
Ctrl+Y Delete from cursor position to end of GET
Ctrl+U Restore current GET to original value
READ Toggle Keys
Key Action
Ins, Ctrl+V Toggle insert mode
READ Exit Keys
Key Action
Ctrl+W, Ctrl+C, PgUp, PgDn Terminate READ saving current GET
Return, Ctrl+M Terminate READ from last GET
Esc Terminate READ without saving current GET
Up arrow Terminate READ from first GET if
ReadExit()=.T.
Down arrow Terminate READ from last GET if
ReadExit()=.T.
Notes
■ Nested READs: To perform a nested READ within a SET KEY,
VALID, or WHEN procedure or user-defined function, declare or create a new GetList, perform a series of @...GET statements, and then READ. When the procedure terminates, the new GetList is released and the previous GetList becomes visible again. See the example below.
■ Quick keys: Pressing Home or End in quick succession goes to
the first or last nonblank character in a Get object's buffer.
■ Terminating a READ: A READ is terminated by executing a BREAK,
CLEAR, CLEAR GETS, or CLEAR ALL from within a SET KEY procedure or a user-defined function initiated by VALID.
■ Updated(): If any Get object buffer was changed during the
■ This example defines several GETs then READs them:
CLEAR
cVar1 := cVar2 := cVar3 := Space(10)
@ 10, 10 SAY "Variable one:" GET cVar1 VALID ;
!Empty(cVar1)
@ 11, 10 SAY "Variable two:" GET cVar2 ;
WHEN RTrim(cVar1) != "One"
@ 12, 10 SAY "Variable three:" GET cVar3 VALID ;
!Empty(cVar3)
READ
■ This example performs a nested READ within a SET KEY, WHEN, or
VALID procedure or user-defined function:
LOCAL cName := Space(10)
@ 10, 10 GET cName VALID SubForm( cName )
READ
RETURN
FUNCTION SubForm( cLookup )
LOCAL GetList := {} // Create new GetList
USE Sales INDEX Salesman NEW
SEEK cLookup
IF Found()
@ 15, 10 GET Salesman // Add Get objects to
@ 16, 10 GET Amount // new GetList
READ // READ from new GetList
ENDIF
CLOSE Sales
RETURN .T. // Release new GetList
scope is the portion of the current database file to RECALL. The default scope is the current record, or NEXT 1. If a condition is specified, the default scope becomes ALL.
WHILElCondition specifies the set of records meeting the condition from the current record until the condition fails.
FORlCondition specifies the conditional set of records to RECALL within the given scope.
Description
RECALL is a database command that restores records marked for deletion in the current work area. This is the inverse of the DELETE command. If DELETED is ON, RECALL can restore the current record or a specific record, if you specify a RECORD scope. Note that once you PACK a database file, all marked records have been physically removed from the file and cannot be recovered.
In a network environment, RECALLing the current record requires an RLock(). RECALLing several records requires an FLock() or EXCLUSIVE USE of the current database file. Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information.
Examples
■ This examples show the results of RECALL:
USE Sales NEW
//
DELETE RECORD 4
? Deleted() // Result: .T.
//
RECALL
? Deleted() // Result: .F.
EVALlCondition specifies a condition that is evaluated either for each record processed or at the interval specified by the EVERY clause. This clause is identical to the EVAL clause of the INDEX command, but must be respecified in order for the reindexing operation to be monitored since the value of lCondition is transient.
EVERYnRecords specifies a numeric expression that modifies how often EVAL is evaluated. When using EVAL, the EVERY option offers a performance enhancement by evaluating the condition for every nth record instead of evaluating each record reindexed. The EVERY keyword is ignored if no EVAL condition is specified.
Description
REINDEX is a database command that rebuilds all open indexes in the current work area. When the reindexing operation finishes, all rebuilt indexes remain open, order is reset to one, and the record pointer is positioned to the first record in the controlling index. If any of the indexes were created with SET UNIQUE ON, REINDEX adds only unique keys to the index. If any of the indexes were created using a FOR condition, only those key values from records matching the condition are added to the index.
In a network environment, REINDEX requires EXCLUSIVE USE of the current database file. Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information.
Caution! REINDEX does not recreate the header of the index file when it recreates the index. Because of this, REINDEX does not help if there is corruption of the file header. To guarantee a valid index, always use INDEX ON in place of REINDEX to rebuild damaged indexes
Notes
Index key order, UNIQUE status, and the FOR condition are known to the index (.ntx) file and are, therefore, respected and maintained by REINDEX.
Examples
■ This example REINDEXes the index open in the current work
area:
USE Sales INDEX Salesman, Territory NEW
REINDEX
■ This example REINDEXes using a progress indicator:
USE Sales INDEX Salesman, Territory NEW
REINDEX EVAL NtxProgress() EVERY 10
FUNCTION NtxProgress
LOCAL cComplete := LTrim(Str((RecNo()/LastRec()) * 100))
@ 23, 00 SAY "Indexing..." + cComplete + "%"
RETURN .T.
RELEASE <idMemvar list>
RELEASE ALL [LIKE | EXCEPT <skeleton>]
Arguments
idMemvar list is a list of private or public variables or arrays to delete.
ALL [LIKE|EXCEPT skeleton] defines the set of visible private memory variables to assign, or to exclude from assignment of, a NIL value. skeleton is the wildcard mask to specify a group of memory variables to delete. The wildcard characters supported are * and ?.
Description
RELEASE is a memory variable command that performs one of two actions depending on how it is specified. If RELEASE is specified with idMemvar list, the specified public and private memory variables and/or arrays are deleted from memory. Previous hidden instances (public or private variables defined in higher-level procedures) become accessible upon termination of the procedure where the variable was originally created.
If RELEASE is specified with any form of the ALL clause, private memory variables created at the current procedure level are assigned a NIL and not deleted until the current procedure or user-defined function terminates. Public variables are unaffected by this form of the RELEASE command. To release public variables, you must RELEASE them explicitly or use CLEAR MEMORY.
Local or static variables are not affected by the RELEASE command. Local variables are released automatically when the procedure or user- defined function (where the variables were declared) terminates. Static variables cannot be released since they exist for the duration of the program.
xcOldFile is the name of the file to be renamed including an extension, and optionally is preceded by a drive and/or path designator. xcOldFile can be a literal string or a character expression enclosed in parentheses.
TOxcNewFile specifies the new file name including extension and optionally prefaced by a drive and/or path designator. xcNewFile can be a literal string or a character expression enclosed in parentheses.
Description
RENAME is a file command that changes the name of a specified file to a new name. If the source directory is different from the target directory, the file moves to the new directory. RENAME does not use SET DEFAULT and SET PATH to locate xcOldFile. Instead, the xcOldFile is renamed only if it is located in the current DOS directory or in the specified path.
In the instance that either xcNewFile exists or is currently open, RENAME does nothing. To trap this condition as an error, use the File() function before executing the command. See the example.
Warning! Files must be CLOSEd before renaming. Attempting to rename an open file will produce unpredictable results. When a database file is RENAMEd, remember that any associated memo (.dbt) file must also be RENAMEd. Failure to do so may compromise the integrity of your program.
Examples
■ This example renames a file, checking for the existence of the
target file before beginning the RENAME operation:
xcOldFile := "OldFile.txt"
xcNewFile := "NewFile.txt"
IF !FILE(xcNewFile)
RENAME (xcOldFile) TO (xcNewFile)
ELSE
? "File already exists"
ENDIF
REPLACE <idField> WITH <exp>
[, <idField2> WITH <exp2>...]
[<scope>] [WHILE <lCondition>] [FOR <lCondition>]
Arguments
idField is the name of the field variable to be assigned a new value. If idField is prefaced with an alias, the assignment takes place in the designated work area.
WITHexp defines the value to assign to idField.
scope is the portion of the current database file to REPLACE. The default is the current record, or NEXT 1. Specifying a condition changes the default to ALL records in the current work area.
WHILElCondition specifies the set of records meeting the condition from the current record until the condition fails.
FORlCondition specifies the conditional set of records to REPLACE within the given scope.
Description
REPLACE is a database command that assigns new values to the contents of one or more field variables in the current record in the specified work areas. The target field variables can be character, date, logical, memo, or numeric. REPLACE performs the same function as the assignment operator (:=) except that it assumes that an unaliased reference is to a field variable. This means that you can assign new values to field variables using assignment statements provided that the field variable references are prefaced with an alias, the FIELD alias, or declared using the FIELD declaration statement.
The default scope of REPLACE is the current record unless a scope or condition is specified. If a scope or condition is specified, the replace operation is performed on each record matching the scope and/or condition.
Warning! When you REPLACE a key field, the index is updated and the relative position of the record pointer within the index is changed. This means that REPLACEing a key field with a scope or a condition may yield an erroneous result. To update a key field, SET ORDER TO 0 before the REPLACE. This ensures that the record pointer moves sequentially in natural order. All open indexes, however, are updated if the key field is REPLACEd.
In a network environment, REPLACEing the current record requires an RLock(). REPLACEing with a scope and/or condition requires an FLock() or EXCLUSIVE USE of the current database file. If a field is being REPLACEd in another work area by specifying its alias, that record must also be locked with an RLock(). Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information.
Examples
■ This example shows a simple use of REPLACE:
USE Customer NEW
APPEND BLANK
USE Invoices NEW
APPEND BLANK
//
REPLACE Charges WITH Customer->Markup * Cost,;
Custid WITH Customer->Custid,;
Customer->TranDate WITH Date()
■ This example uses assignment statements in place of the
REPLACE command:
FIELD->Charges := Customer->Markup * FIELD->Cost
FIELD->Custid := Customer->Custid
Customer->TranDate := Date()
xcReport is the name of the report form (.frm) file that contains the definition of the REPORT. If an extension is not specified, (.frm) is assumed. xcReport can be specified as a literal string or as a character expression enclosed in parentheses.
TO PRINTER echoes output to the printer.
TO FILExcFile echoes output without form feed characters (ASCII 12) to a file. If a file extension is not specified, .txt is added. You can specify xcFile as a literal string or as a character expression enclosed in parentheses.
NOCONSOLE suppresses all REPORT FORM output to the console. If not specified, output automatically displays to the console unless SET CONSOLE is OFF.
scope is the portion of the current database file to report. The default scope is ALL.
WHILElCondition specifies the set of records meeting the condition from the current record until the condition fails.
FORlCondition specifies the conditional set of records to report within the given scope.
PLAIN suppresses the display of the date and page number, and causes the report to print without page breaks. In addition, the report title and column headings display only at the top of the report.
HEADING places the result of cHeading on the first line of each page. cHeading is evaluated only once at the beginning of the report before the record pointer is moved. If both PLAIN and HEADING are specified, PLAIN takes precedence.
NOEJECT suppresses the initial page eject when the TO PRINTER clause is used.
SUMMARY causes REPORT FORM to display only group, subgroup, and grand total lines. Detail lines are suppressed.
Description
REPORT FORM is a console command that sequentially accesses records in the current work area and displays a tabular and optionally grouped report with page and column headings from a definition held in a .frm file. The actual REPORT FORM file (.frm) is created using RL.EXE or dBASE III PLUS. Refer to the "Report and Label Utility" chapter in the Programming and Utilities Guide for more information about creating report definitions.
When invoked, REPORT FORM sends output to the screen and, optionally, to the printer and/or a file. To suppress output to the screen while printing or echoing output to a file, SET CONSOLE OFF or use the NOCONSOLE keyword before the REPORT FORM invocation.
When invoked, REPORT FORM searches the current SET PATH drive and directory if the xcReport file is not found in the current directory and the path is not specified.
Notes
■ Interrupting REPORT FORM: To allow the user to interrupt a
REPORT FORM, use Inkey() to test for an interrupt key press, as a part of the FOR condition. See the example below.
■ Printer margin: REPORT FORM obeys the current SET MARGIN value
for output echoed to the printer.
■ Forcing formfeed characters into an output file: To include
form feed characters when sending a REPORT FORM TO FILE, redirect printer output to a file using SET PRINTER like this:
SET PRINTER TOxcFileREPORT FORMxcReportTO PRINTER SET PRINTER TO
■ Reporting in a network environment: REPORT FORM commands
executed in a network environment can be affected by changes made to database files by other users while the report is in progress. For example, if a user changes a key value from "A" to "Z" while the report is printing, the same record could appear twice.
Examples
■ This example uses both a literal and an extended expression to
execute a REPORT FORM:
LOCAL xcReport := "Sales"
USE Sales INDEX Sales NEW
REPORT FORM Sales TO PRINTER FOR Branch = "100";
HEADING "Branch 100"
REPORT FORM (xcReport) TO PRINTER FOR Branch != "100"
■ This example interrupts a REPORT FORM using Inkey() to test
whether the user has pressed the Esc key:
#define K_ESC 27
USE Sales INDEX Sales NEW
REPORT FORM Sales WHILE Inkey() != K_ESC
idModule list is the list of modules that will be linked into the current executable (.EXE) file.
Description
REQUEST is a declaration statement that defines a list of module identifiers to the linker. Like all other declaration statements, a REQUEST statement must be specified before any executable statements in either the program file, or a procedure or user-defined function definition.
During the compilation of CA-Clipper source code, all explicit references to procedures and user-defined functions are made to the linker. In some instances, within a source file, there may be no references made to procedure or user-defined function names until runtime. REQUEST resolves this situation by forcing the named procedures or user-defined functions to be linked even if they are not explicitly referenced in the source file. This is important in several instances:
■ Procedures, user-defined functions, or formats referenced with
macro expressions or variables
■ Procedures and user-defined functions used in REPORT and LABEL
FORMs and not referenced in the source code
■ User-defined functions used in index keys and not referenced
■ Initialization procedures declared with the INIT PROCEDURE
statement
■ Exit procedures declared with the EXIT PROCEDURE statement
To group common REQUESTs together, place them in a header file and then include (#include) the header file into each program file (.prg) that might indirectly use them.
Examples
■ This example shows a typical header file consisting of common
REQUESTs for REPORT FORMs:
// Request.ch
REQUEST HardCR
REQUEST Tone
REQUEST MemoTran
REQUEST StrTran
Retrieve memory variables from a memory (.mem) file
Syntax
RESTORE FROM <xcMemFile> [ADDITIVE]
Arguments
xcMemFile is the memory (.mem) file to load from disk. If an extension is not specified, the extension .mem is assumed. The file name may be specified as a literal string or as a character expression enclosed in parentheses.
ADDITIVE causes memory variables loaded from the memory file to be added to the existing pool of memory variables.
Description
RESTORE is a memory variable command that recreates public and private variables previously SAVEd to a memory (.mem) file and initializes them with their former values. The scope of the variable is not SAVEd with the variable, but is instead established when the variable is RESTOREd. Arrays and local variables cannot be SAVEd or RESTOREd.
When memory variables are RESTOREd, they are recreated as private variables with the scope of the current procedure or user-defined function unless they exist as public variables and you specify the ADDITIVE clause. If ADDITIVE is specified, public and private variables with the same names are overwritten unless hidden with PRIVATE. If ADDITIVE is not specified, all public and private variables are released before the memory file is loaded.
Local and static variables are unaffected by RESTORE. If a local or static variable has been declared in the current procedure or user- defined function and a variable with the same name is RESTOREd, only the local or static variable is visible unless references to the RESTOREd variable are prefaced with the MEMVAR alias.
Examples
■ This example demonstrates a typical application of SAVE and
RESTORE. Here memory variables containing screens are SAVEd TO and
RESTOREd FROM memory files:
// Create and use a pseudoarray of screens
SAVE SCREEN TO cScreen1
SAVE ALL LIKE cScreen* TO Screens
//
<statements>...
//
RESTORE FROM Screens ADDITIVE
nNumber = "1"
RESTORE SCREEN FROM ("cScreen" + nNumber)
FROMcScreen specifies a character expression to display to the screen.
Description
RESTORE SCREEN is a command synonym for the RestScreen() function that redisplays a previously saved screen, and is used with SAVE SCREEN to avoid repainting the original screen painted with @...SAY, @...GET, and ? commands.
RESTORE SCREEN works in two ways depending on whether or not you specify the FROM clause. If you specify the FROM clause, the SCREEN is RESTOREd FROMcScreen. cScreen is a character expression, usually a variable assigned a screen image by SAVE SCREEN. If you do not specify the FROM clause, the SCREEN is RESTOREd from the default save screen buffer created by SAVE SCREEN specified without the TO clause.
SaveScreen() and RESTORESCREEN() functions supersede SAVE SCREEN and RESTORE SCREEN commands.
RESTORE SCREEN is a compatibility command and therefore not recommended.
Warning! SAVE SCREEN, RESTORE SCREEN, SaveScreen(), and RestScreen() are supported when using the default (IBM PC memory mapped) screen driver. Other screen drivers may not support saving and restoring screens.
Examples
■ This example displays a small alert pop-up box using SAVE and
RESTORE SCREEN:
IF FileAlert()
COPY FILE Them.txt TO My.txt
ELSE
BREAK
ENDIF
RETURN
FUNCTION FileAlert
LOCAL lAnswer := .F., cScreen
SAVE SCREEN TO cScreen
@ 10, 10 CLEAR TO 12, 45
@ 10, 10 TO 12, 45 DOUBLE
@ 11, 12 SAY "File exists, overwrite? (y/n) ";
GET lAnswer PICTURE "Y"
READ
RESTORE SCREEN FROM cScreen
RETURN lAnswer
Terminate a procedure, user-defined function, or program
Syntax
RETURN [<exp>]
Arguments
exp is an expression of any type that evaluates to the return value for user-defined functions. If a user-defined function terminates without executing a RETURN statement, the return value is NIL.
Description
RETURN terminates a procedure, user-defined function, or program by returning control to either the calling procedure or user-defined function. When RETURN executes in the highest level procedure, control passes to the operating system. All private variables created and local variables declared in the current procedure or user-defined function are released when control returns to the calling procedure.
There can be more than one RETURN in a procedure or user-defined function. A procedure or user-defined function need not, however, end with a RETURN. Since user-defined functions must return values, each must contain at least one RETURN statement with an argument.
Note: A procedure or user-defined function definition is terminated by a PROCEDURE statement, a FUNCTION statement, or end of file but not by a RETURN statement.
Notes
■ Arrays: Since array is a data type like any other data type,
instances of array type are really values like character strings and, therefore, can be RETURNed from a user-defined function.
■ RETURN TO MASTER: CA-Clipper does not support RETURN TO MASTER
or any other form of RETURN specifying the level to which the call is to return. You can, however, simulate these operations with BEGIN SEQUENCE...END.
Examples
■ These examples illustrate the general form of the RETURN
statement in a procedure and in a user-defined function:
PROCEDURE <idProcedure>
//
<statements>...
//
RETURN
FUNCTION <idFunction>
//
<statements>...
//
RETURN <expReturn>
■ This example returns an array, created in a user-defined
function, to a calling procedure or user-defined function:
FUNCTION PassArrayBack
PRIVATE aArray[10][10]
aArray[1][1] = "myString"
RETURN aArray
Return a substring beginning with the rightmost character
Syntax
Right(<cString>, <nCount>) → cSubString
Arguments
cString is the character string from which to extract characters.
nCount is the number of characters to extract.
Returns
Right() returns the rightmost nCount characters of cString. If nCount is zero, Right() returns a null string (""). If nCount is negative or larger than the length of the character string, Right() returns cString. The maximum string size is 65,535 (64K) bytes.
Description
Right() is a character function that extracts a substring beginning with the rightmost character in cString. It is the same as the character expression, SubStr(cString, nCount). For example, Right("ABC", 1) is the same as SubStr("ABC", -1). Right() is related to Left(), which extracts a substring beginning with the leftmost character in cString.
The Right(), Left(), and SubStr() functions are often used with both the At() and RAt() functions to locate either the first and/or the last position of a substring before extracting it.
Examples
■ This example shows the relationship between Right() and
SubStr():
? Right("ABCDEF", 3) // Result: DEF
? SubStr("ABCDEF", -3) // Result: DEF
■ This example extracts a substring from the end of another
string up to the last occurrence of a comma:
LOCAL cName := "James,William"
? Right(cName,;
Len(cName) - RAt(",", cName) - 1) // Result: William
RLock() returns true (.T.) if the record lock is obtained; otherwise, it returns false (.F.).
Description
RLock() is a network function that locks the current record, preventing other users from updating the record until the lock is released. RLock() provides a shared lock, allowing other users read-only access to the locked record while allowing only the current user to modify it. A record lock remains until another record is locked, an UNLOCK is executed, the current database file is closed, or an FLock() is obtained on the current database file.
For each invocation of RLock(), there is one attempt to lock the current record, and the result is returned as a logical value. An attempt to obtain a record lock fails if another user currently has a file or record lock on that particular record, or EXCLUSIVE USE of the database file. An attempt to RLock() in an empty database returns true (.T.).
By default, RLock() operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression (see example below). This feature is useful since RLock() does not automatically attempt a record lock for related files.
As a general rule, RLock() operates solely on the current record. This includes the following commands:
■ @...GET
■ DELETE (single record)
■ RECALL (single record)
■ REPLACE (single record)
Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information.
Notes
■ SET RELATION: CA-Clipper does not automatically lock all
records in the relation chain when you lock the current work area record. Also, an UNLOCK has no effect on related work areas.
Examples
■ This example deletes a record in a network environment, using
RLock():
USE Customer INDEX CustName SHARED NEW
SEEK "Smith"
IF Found()
IF RLock()
DELETE
? "Smith deleted"
ELSE
? "Record in use by another"
ENDIF
ELSE
? "Smith not in Customer file"
ENDIF
CLOSE
■ This example specifies RLock() as an aliased expression to
lock a record in an unselected work area:
USE Sales SHARED NEW
USE Customer SHARED NEW
//
IF !Sales->(RLock())
? "The current Sales record is in use by another"
ENDIF
Return a numeric value rounded to a specified number of digits
Syntax
Round(<nNumber>, <nDecimals>) → nRounded
Arguments
nNumber is the numeric value to be rounded.
nDecimals defines the number of decimal places to retain. Specifying a negative nDecimals value rounds whole number digits.
Returns
Round() returns a numeric value.
Description
Round() is a numeric function that rounds nNumber to the number of places specified by nDecimals. Specifying a zero or negative value for nDecimals allows rounding of whole numbers. A negative nDecimals indicates the number of digits to the left of the decimal point to round. Digits between five to nine (inclusive) are rounded up. Digits below five are rounded down.
The display of the return value does not obey the DECIMALS setting unless SET FIXED is ON. With SET FIXED OFF, the display of the return value contains as many decimal digits as you specify for nDecimals, or zero, if nDecimals is less than one.
Examples
■ These examples round values with decimal digits:
SET DECIMALS TO 2
SET FIXED ON
//
? Round(10.4, 0) // Result: 10.00
? Round(10.5, 0) // Result: 11.00
? Round(10.51, 0) // Result: 11.00
? Round(10.49999999999999, 2) // Result: 10.50
■ These examples use a negative <nDecimals> argument to round
numeric values to whole number values:
? Round(101.99, -1) // Result: 100.00
? Round(109.99, -1) // Result: 110.00
? Round(109.99, -2) // Result: 100.00
Row() returns the cursor row position as an integer numeric value. The range of the return value is zero to MaxRow().
Description
Row() is a screen function that returns the current row or line position of the screen cursor. The value of Row() is updated by both console and full-screen commands and functions. @...SAY only updates Row() when the current DEVICE is the SCREEN.
Row() is used with Col() and all variations of the @ command to position the cursor to a new line relative to the current line. In particular, you can use Row() and Col() to create screen position-independent procedures or functions where you pass the upper-left row and column as parameters.
Row() is related to PRow() and PCol(), which track the current printhead position instead of the screen cursor position.
Examples
■ In this example, Row() simulates the LIST command, displaying
text on the same line but in different columns:
LOCAL nRow
USE Customer INDEX CustName NEW
DO WHILE .NOT. Eof()
CLS
@ 1, 1 SAY PadR("Name", Len(CustName))
@ Row(), Col() + 2 SAY PadR("Address", ;
Len(Address))
@ Row(), Col() + 2 SAY PadR("Phone", Len(Phone))
nRow = 0
DO WHILE nRow++ <= 15 .AND. (!Eof())
@ Row() + 1, 1 SAY CustName
@ Row(), Col() + 2 SAY Address
@ Row(), Col() + 2 SAY Phone
SKIP
ENDDO
WAIT
ENDDO
CLOSE Customer
cString is the character string to be copied without trailing spaces.
Returns
RTrim() returns a copy of cString with the trailing spaces removed. If cString is a null string ("") or all spaces, RTrim() returns a null string ("").
Description
RTrim() is a character function that formats character strings. It is useful when you want to delete trailing spaces while concatenating strings. This is typically the case with database fields which are stored in fixed-width format. For example, you can use RTrim() to concatenate first and last name fields to form a name string.
RTrim() is related to LTrim() which removes leading spaces, and AllTrim() which removes both leading and trailing spaces. The inverse of AllTrim(), LTrim(), and RTrim() are the PadC(), PadR(), and PadL() functions which center, right-justify, or left-justify character strings by padding them with fill characters. RTrim() is exactly the same as Trim() in function.
Notes
■ Space characters: The RTrim() function treats carriage
returns, line feeds, and tabs as space characters and removes these as well.
Examples
■ This is a user-defined function in which RTrim() formats city,
state, and zip code fields for labels or form letters:
FUNCTION CityState(cCity, cState, cZip)
RETURN RTrim(cCity) + ", " ;
+ RTrim(cState) + " " + cZip
■ In this example the user-defined function, CityState(),
displays a record from Customer.dbf:
USE Customer INDEX CustName NEW
SEEK "Kate"
? CityState(City, State, ZipCode)
// Result: Athens, GA 10066
xcCommandLine is any executable program including resident DOS commands and COMMAND.COM. It may be specified either as a literal string or as a character expression enclosed in parentheses.
Description
RUN executes a DOS command or program from within a compiled application. When you RUN a DOS program, CA-Clipper executes another copy of COMMAND.COM, passing the DOS command line at the same time. This has two implications. First, you must have enough memory for COMMAND.COM (5K for DOS 6.2) and the program you wish to execute. Second, COMMAND.COM must be available on the path specified by COMSPEC (the default is the root directory of the disk where you boot DOS). If COMMAND.COM is not located on this disk or the disk is changed, SET COMSPEC to the new location prior to running the CA-Clipper application. Note that SET DEFAULT and SET PATH have no effect on RUN.
The ! form of the RUN command is provided for compatibility purposes only and, therefore, is not recommended.
Warning! Do not RUN memory-resident programs from within CA-Clipper since you may lose memory when the control returns to your application program.
Examples
■ This example uses RUN with MemoRead() and MemoWrit() to create
a user-defined function that calls a text editor with the current
memo field:
lSuccess = EditorMemo("Qedit", "Notes")
RETURN
FUNCTION EditorMemo( cEditor, cMemofld )
IF MemoWrit("Clipedit.tmp", &cMemofld.)
RUN (cEditor + " Clipedit.tmp")
REPLACE &cMemofld. WITH MemoRead("Clipedit.tmp")
ERASE Clipedit.tmp
RETURN .T.
ELSE
RETURN .F.
ENDIF
■ One of the options you may want to give your users is direct
access to DOS. Do this with:
RUN COMMAND
To make it easier for the user to return to the application program,
change the DOS prompt in the application batch file like this:
REM Application Batch File
ECHO OFF
PROMPT DOS Access: Type EXIT to return to ;
application$_$p$g
<your application program>
PROMPT $p$g
Then, instruct the user to execute the application batch file in
place of the application .EXE file.
nTop, nLeft, nBottom, and nRight define the coordinates of the screen region to be saved. If either nBottom or nRight is greater than MaxRow() or MaxCol(), the screen is clipped. If you specify no coordinates, the entire screen (i.e., from 0,0 to MaxRow(), MaxCol()) is saved.
Returns
SaveScreen() returns the specified screen region as a character string.
Description
SaveScreen() is a screen function that saves a screen region to a variable of any storage class including a field variable. Later, you can redisplay the saved screen image to the same or a new location using RestScreen(). Screen regions are usually saved and restored when using a pop-up menu routine or dragging a screen object.
Warning! SAVE SCREEN, RESTORE SCREEN, SaveScreen(), and RestScreen() are supported when using the default (IBM PC memory mapped) screen driver. Other screen drivers may not support saving and restoring screens.
Examples
■ The following user-defined function creates a pop-up menu
using AChoice() with SaveScreen() and RestScreen(), returning the
selection in the array of choices:
FUNCTION PopMenu( nTop, nLeft, nBottom, nRight, ;
aItems, cColor )
LOCAL cScreen, nChoice, cLastColor := ;
SetColor(cColor)
//
cScreen:= SaveScreen(nTop, nLeft, nBottom, nRight)
@ nTop, nLeft TO nBottom, nRight DOUBLE
//
nChoice:= AChoice(++nTop, ++nLeft, ;
--nBottom, --nRight, aItems)
//
RestScreen(--nTop, --nLeft, ++nBottom, ++nRight, ;
cScreen)
SetColor(cLastColor)
RETURN nChoice
SAVE TO <xcMemFile> [ALL [LIKE | EXCEPT <skeleton>]]
Arguments
xcMemFile is the memory (.mem) file to SAVE to disk. You may specify the file name as a literal string or as a character expression enclosed in parentheses. If you specify no extension, the file is created with a .mem extension.
ALL [LIKE|EXCEPT skeleton] defines the set of visible private and public memory variables to save to xcMemFile. skeleton is the wildcard mask that characterizes a group of memory variables to SAVE. The wildcard characters supported are * and ?.
Description
SAVE copies public and private memory variables visible within the current procedure or user-defined function to a memory (.mem) file. Arrays and local and static variables, however, cannot be SAVEd. When variables are SAVEd, they are copied without any reference to scope. Variables hidden by PRIVATE or LOCAL declarations are not SAVEd.
If you specify the ALL LIKE clause, variable names matching the skeleton mask are saved. By contrast, if you specify ALL EXCEPT, variable names not matching the skeleton are saved.
You can specify a skeleton that includes wildcard characters. The * wildcard character matches any group of adjacent characters ending a variable name and can be specified only at the end of the skeleton. The ? wildcard character matches any single character and can be specified anywhere within the skeleton.
Examples
■ This example saves all visible private and public variables to
Temp.mem:
PRIVATE cOne := "1"
SAVE ALL TO Temp
■ This example saves all visible private and public variables
with names beginning with "c" to Myvars.mem:
SAVE ALL LIKE c* TO MyVars
■ This example saves all visible private and public variables
with names that do not begin with "c" to Myvars2.mem:
SAVE ALL EXCEPT c* TO MyVars2
TOidVar specifies a variable to contain the current screen contents as a character value. If idVar is not visible or does not exist, a private memory variable is created and assigned to the screen.
Description
SAVE SCREEN is a command synonym for the SaveScreen() function that saves the screen from 0, 0 to MaxRow(), MaxCol() in a default screen buffer, or in an optional variable. If the screen is saved to a variable, the variable can be any storage class including field, local, static, or an array element. Note, however, you cannot SAVE an array or local or static variable to .mem files to save multiple screens to disk.
SAVE SCREEN is used with RESTORE SCREEN to eliminate repainting an original screen that has been temporarily replaced. You may save multiple screens by assigning each screen to a separate variable.
SAVE SCREEN is a compatibility command and not recommended. It is superseded by the SaveScreen() function which can save partial or full screens.
Warning! SAVE SCREEN, RESTORE SCREEN, SaveScreen(), and RestScreen() are supported when using the default (IBM PC memory mapped) screen driver. Other screen drivers may not support saving and restoring screens.
Examples
■ This code skeleton uses a static array to store saved screens:
STATIC aScreens[10]
SAVE SCREEN TO aScreens[1]
//
<statements>...
//
RESTORE SCREEN FROM aScreens[1]
■ This example saves and restores screens using a database file:
USE Screens INDEX Name NEW
APPEND BLANK
Screens->Name := "Screen001" // Save the screen name
SAVE SCREEN TO Screens->Image // Save a new screen image
//
<statements>...
//
SEEK "Screen001" // Find the screen
RESTORE SCREEN FROM Screens->Image // Restore it
nTop, nLeft, nBottom, and nRight define the scroll region coordinates. Row and column values can range from 0, 0 to MaxRow(), MaxCol(). If you do not specify coordinate arguments, the dimensions of the visible display are used.
nVert defines the number of rows to scroll vertically. A positive value scrolls up the specified number of rows. A negative value scrolls down the specified number of rows. A value of zero disables vertical scrolling. If nVert is not specified, zero is assumed.
nHoriz defines the number of rows to scroll horizontally. A positive value scrolls left the specified number of columns. A negative value scrolls right the specified number of columns. A value of zero disables horizontal scrolling. If nHoriz is not specified, zero is assumed.
If you supply neither the nVert nor nHoriz parameters to Scroll(), the area specified by the first four parameters will be blanked.
Warning! Horizontal scrolling is not supported on all of the alternate terminal drivers (i.e., ANSITERM, NOVTERM, PCBIOS).
Returns
Scroll() always returns NIL.
Description
Scroll() is a screen function that scrolls a screen region up or down a specified number of rows. When a screen scrolls up, the first line of the region is erased, all other lines are moved up, and a blank line is displayed in the current standard color on the bottom line of the specified region. If the region scrolls down, the operation is reversed. If the screen region is scrolled more than one line, this process is repeated.
Scroll() is used primarily to display status information into a defined screen region. Each time a new message is displayed, the screen region scrolls up one line and a new line displays at the bottom.
Examples
■ This user-defined function displays a message string at the
bottom of a screen region after scrolling the region up one line:
FUNCTION ScrollUp( nTop, nLeft, nBottom, nRight, ;
expDisplay )
//
Scroll(nTop, nLeft, nBottom, nRight, 1)
@ nBottom, nLeft SAY expDisplay
//
RETURN NIL
Scroll bars allow users to view data that exists beyond the limit of a window. By scrolling up, down, left, or right, you can reveal previously hidden pieces of data. Applications should provide scroll bars for any screen in which the data displayed is larger than the current window.
Methods link
Class Function
ScrollBar() Create a new ScrollBar object
Scrollbar (nStart, nEnd, nOffset, [bSBlock]
[,nOrient]) → oScrollBar
Arguments
nStart is a numeric value that indicates the screen position where the scroll bar begins. nStart refers to the topmost row of a vertically oriented scroll bar, or the leftmost column of a horizontally oriented scroll bar.
nEnd is a numeric value that indicates the screen position where the scroll bar ends. nEnd refers to the bottommost row of a vertically oriented scroll bar, or the rightmost column of a horizontally oriented scroll bar.
nOffset is a numeric value that indicates the screen column of a vertically oriented scroll bar or the screen row of a horizontally oriented scroll bar.
bSBlock is an optional code block that, when present, is evaluated immediately before and after the ScrollBar object's state changes.
nOrient is an optional numeric value that indicates whether the scroll bar is vertically or horizontally oriented. The default is a vertically oriented scroll bar.
Returns
Returns a ScrollBar object when all of the required arguments are present; otherwise, ScrollBar() returns NIL.
Exported Instance Variables
barLength Marks number of positions scroll bar client area occupies
barlength
Contains a numeric value that indicates the number of character positions that the scroll bar client area occupies. Each position refers to one row for a vertically oriented scroll bar or one column for a horizontally oriented scroll bar. The client area is the area between (but not including) the scroll bar's previous arrow and its next arrow.
bitmaps An array of bitmap files to be displayed
bitmaps (Assignable)
Contains an array of exactly three elements. The first element of this array is the file name of the bitmap to be displayed at the top of a vertical scroll bar or to the left of a horizontal scroll bar. The second element of this array is the file name of the bitmap to be displayed at the bottom of a vertical scroll bar or to the right of a horizontal scroll bar. The third element of this array is the file name of the bitmap to be used as the thumbwheel.
Drive and directory names are not allowed; the file name extension is required. A bitmap file can be stored as a file on disk or in a bitmap library. If stored as a file, the file must reside in the same directory as the application. If stored in a bitmap library, the library must reside in the same directory as the application and it also must have the same name as the application with a .BML extension.
CA-Clipper will search for the file name first and then, if it is not found, it will search in the bitmap library. If no file is found either on disk or in the library, no bitmap will be displayed.
If this instance variable is not used, and the application is running in graphic mode, the files ARROW_L.BMU, ARROW_R.BMU, and ARROW_E.BMU will be used for a horizontal scroll bar and the files ARROW_U.BMU, ARROW_D.BMU, and ARROW_E.BMU will be used for a horizontal scroll bar.
This instance variable only affects applications running in graphic mode and is ignored in text mode.
cargo User-definable variable
cargo (Assignable)
Contains a value of any type that is ignored by the ScrollBar object. ScrollBar:cargo is provided as a user-definable slot allowing arbitrary information to be attached to a ScrollBar object and retrieved later.
colorSpec Indicates the colors used by the ScrollBa:display() method
colorSpec (Assignable)
Contains a character string that indicates the color attributes that are used by the scroll bar's display() method. The string must contain two color specifiers.
Note: In graphic mode, colorSpec position 2 has no affect and is ignored.
ScrollBar Color Attributes
Position Applies To Default Value from
in colorSpec System Color Setting
1 The scroll bar's client area Unselected
2 The previous arrow, next arrow, and Enhanced
thumb
Note: The colors available to a DOS application are more limited than those for a Windows application. The only colors available to you here are listed in the drop-down list box of the Workbench Properties window for that item.
current Indicates number of current item the scroll bar refers to
current (Assignable)
Contains a numeric value that indicates the number of the current item to which the scroll bar refers.
end Indicates the screen position of the scroll bar's next arrow
end (Assignable)
Contains a numeric value that indicates the screen position of the scroll bar's next arrow. ScrollBar:end refers to the bottommost row of a vertically oriented scroll bar, or the rightmost column of a horizontally oriented scroll bar.
offset Indicates column or row of vertical or horizontal scroll bar
offset (Assignable)
Contains a numeric value that indicates the screen column of a vertically oriented scroll bar or the screen row of a horizontally oriented scroll bar.
orient Indicates if scroll bar is vertically/horizontally oriented
orient (Assignable)
Contains a numeric value that indicates whether the scroll bar is vertically or horizontally oriented.
Scroll Bar Types
Value Constant Description
1 SCROLL_VERTICAL Vertical scroll bar
2 SCROLL_HORIZONTAL Horizontal scroll bar
Button.ch contains manifest constants for the ScrollBar:orient value.
sBlock Code block evaluated at every state change
sblock (Assignable)
Contains an optional code block that, when present, is evaluated immediately after the ScrollBar object's state changes. The code block takes no implicit arguments.
This code block is included in the ScrollBar class to provide a method of indicating when a state change event has occurred. The name "sblock" refers to state block.
start Indicates the screen position of scroll bar's previous arrow
start (Assignable)
Contains a numeric value that indicates the screen position of the scroll bar's previous arrow. ScrollBar:start refers to the topmost row of a vertically oriented scroll bar, or the leftmost column of a horizontally oriented scroll bar.
style Indicates characters used by the ScrollBar:display() method
style (Assignable)
Contains a character string that indicates the characters that are used by the scroll bar's display() method. The string must contain four characters. The first character is the previous arrow character. Its default value is the up arrow character for a vertically oriented scroll bar and the left arrow character for a horizontally oriented scroll bar. The second character is the client area character. Its default value is the character. The third is the thumb character. Its default is the character. The fourth character is the next arrow character. Its default value is the down arrow character for a vertically oriented scroll bar or the right arrow character for a horizontally oriented scroll bar.
Note: In graphic mode, the style instance variable is ignored.
thumbPos Indicates relative position of the thumb within scroll bar
thumbpos
Contains a numeric value that indicates the relative screen position of the thumb within a scroll bar. Valid ScrollBar:thumbpos values range from 1 to ScrollBar:barlength.
total Indicates the total number of items the scroll bar refers to
total (Assignable)
Contains a numeric value that indicates the total number of items to which the scroll bar refers.
Exported Methods
display() Shows a scroll bar, including its thumb, on the screen
oScrollBar:display() → self
display() is a method of the ScrollBar class that is used for showing a scroll bar including its thumb on the screen. display() uses the values of the following instance variables to correctly show the scroll bar in its current context, in addition to providing maximum flexibility in the manner a scroll bar appears on the screen: colorSpec, end, offset, orient, start, style, and thumbPos.
update() Changes the thumb position on the screen
oScrollBar:update() → self
update() is a method of the ScrollBar class that is used for changing the thumb position on the screen. update() uses the values of the following instance variables to correctly show the thumb in its current context in addition to providing maximum flexibility in the manner a scroll bar thumb appears on the screen: colorSpec, offset, orient, stable, start, style, and thumbPos.
HitTest() Indicates position of mouse cursor relative to scroll bar
oScrollBar:hitTest( nMouseRow, nMouseCol )
→ nHitStatus
nMouseRow is a numeric value that indicates the current screen row position of the mouse cursor.
nMouseCol is a numeric value that indicates the current screen column position of the mouse cursor.
Returns a numeric value that indicates the action to perform based on the logical position of the mouse cursor in the scroll bar's region of the screen.
Scroll Bar hittest Return Values
Value Constant Mouse Cursor Position
0 HTNOWHERE Not within the scroll bar's region of
the screen
-3073 HTSCROLLTHUMBDRAG On the thumb
-3074 HTSCROLLUNITDEC On the previous arrow
-3075 HTSCROLLUNITINC On the next arrow
-3076 HTSCROLLBLOCKDEC Between the previous arrow and the
thumb
-3077 HTSCROLLBLOCKINC Between the thumb and the next arrow
Button.ch contains manifest constants for the ScrollBar:hitTest() return value.
HitTest() is a method of the ScrollBar class that is used for determining if the mouse cursor is within the region of the screen that the scroll bar occupies.
Examples
■ This example creates a vertical scroll bar from row 2 to 10:
oScr:=(2,10,0)
Return the number of seconds elapsed since midnight
Syntax
Seconds() → nSeconds
Returns
Seconds() returns the system time as a numeric value in the form seconds.hundredths. The numeric value returned is the number of seconds elapsed since midnight, and is based on a twenty-four hour clock in a range from 0 to 86399.
Description
Seconds() is a time function that provides a simple method of calculating elapsed time during program execution, based on the system clock. It is related to the Time() function which returns the system time as a string in the form hh:mm:ss.
Examples
■ This example contrasts the value of Time() with Seconds():
? Time() // Result: 10:00:00
? Seconds() // Result: 36000.00
■ This example uses Seconds() to track elapsed time in seconds:
LOCAL nStart, nElapsed
nStart:= Seconds()
.
. <statements>
.
nElapsed:= Seconds() - nStart
? "Elapsed: " + LTrim(Str(nElapsed)) + " seconds"
Determine the work area number of a specified alias
Syntax
Select([<cAlias>]) → nWorkArea
Arguments
cAlias is the target work area alias name.
Returns
Select() returns the work area of the specified alias as an integer numeric value.
Description
Select() is a database function that determines the work area number of an alias. The number returned can range from 0 to 250. If cAlias is not specified, the current work area number is returned. If cAlias is specified and the alias does not exist, Select() returns zero.
Note: The Select() function and SELECT command specified with an extended expression argument look somewhat alike. This should not be a problem since the Select() function is not very useful on a line by itself.
Examples
■ This example uses Select() to determine which work area
USE...NEW selected:
USE Sales NEW
SELECT 1
? Select("Sales") // Result: 4
■ To reselect the value returned from the Select() function, use
the SELECT command with the syntax, SELECT (<idMemvar>), like this:
USE Sales NEW
nWorkArea:= Select()
USE Customer NEW
SELECT (nWorkArea)
nSpecifier is a numeric value that identifies the setting to be inspected or changed. nSpecifier should be supplied as a manifest constant (see below).
expNewSetting is an optional argument that specifies a new value for the nSpecifier. The type of expNewSetting depends on nSpecifier.
lOpenMode is a logical value that indicates whether or not files opened for the following settings,
_SET_ALTFILE, _SET_PRINTFILE, _SET_EXTRAFILE
should be truncated or opened in append mode. A value of false (.F.) means the file should be truncated. A value of true (.T.) means the file should be opened in append mode. In either case, if the file does not exist, it is created.
If this argument is not specified, the default is append mode.
Returns
Set() returns the current value of the specified setting.
Description
Set() is a system function that lets you inspect or change the values of the CA-Clipper system settings. For information on the meaning and legal values for a particular setting, refer to the associated command or function.
Use a manifest constant to specify the setting to be inspected or changed. These constants are defined in a header file called set.ch. This header file should be included at the top of any source file which uses Set().
Set.ch also defines a constant called _SET_COUNT. This constant is equal to the number of settings that can be changed or inspected with Set(), allowing the construction of a generic function that preserves all settings (see example below).
Note: The numeric values of the manifest constants in set.ch are version-dependent and should never be used directly; the manifest constants should always be used.
If nSpecifier or expNewSetting is invalid, the call to Set() is ignored.
Constant Value Type Associated Command or Function
_SET_EXACT Logical SET EXACT
_SET_FIXED Logical SET FIXED
_SET_DECIMALS Numeric SET DECIMALS
_SET_DATEFORMAT Character SET DATE
_SET_EPOCH Numeric SET EPOCH
_SET_PATH Character SET PATH
_SET_DEFAULT Character SET DEFAULT
_SET_EXCLUSIVE Logical SET EXCLUSIVE
_SET_SOFTSEEK Logical SET SOFTSEEK
_SET_UNIQUE Logical SET UNIQUE
_SET_DELETED Logical SET DELETED
_SET_CANCEL Logical SetCancel()
_SET_DEBUG Numeric AltD()
_SET_COLOR Character SetColor()
_SET_CURSOR Numeric SetCursor()
_SET_CONSOLE Logical SET CONSOLE
_SET_ALTERNATE Logical SET ALTERNATE
_SET_ALTFILE Character SET ALTERNATE TO
_SET_DEVICE Character SET DEVICE
_SET_PRINTER Logical SET PRINTER
_SET_PRINTFILE Character SET PRINTER TO
_SET_MARGIN Numeric SET MARGIN
_SET_BELL Logical SET BELL
_SET_CONFIRM Logical SET CONFIRM
_SET_ESCAPE Logical SET ESCAPE
_SET_INSERT Logical ReadInsert()
_SET_EXIT Logical ReadExit()
_SET_INTENSITY Logical SET INTENSITY
_SET_SCOREBOARD Logical SET SCOREBOARD
_SET_DELIMITERS Logical SET DELIMITERS
_SET_DELIMCHARS Character SET DELIMITERS TO
_SET_WRAP Logical SET WRAP
_SET_MESSAGE Numeric SET MESSAGE
_SET_MCENTER Logical SET MESSAGE
Note: _SET_EXTRAFILE and _SET_SCROLLBREAK have no corresponding commands. _SET_EXTRAFILE lets you specify an additional alternate file, and _SET_SCROLLBREAK lets you toggle the interpretation of Ctrl+S.
Examples
■ In this example a user-defined function preserves or restores
all global settings. This function might be used on entry to a
subsystem to ensure that the subsystem does not affect the state of
the program that called it:
#include "Set.ch"
//
FUNCTION SetAll( aNewSets )
LOCAL aCurrentSets[_SET_COUNT], nCurrent
IF ( aNewSets != NIL ) // Set new and return current
FOR nCurrent := 1 TO _SET_COUNT
aCurrentSets[nCurrent] := ;
Set(nCurrent, aNewSets[nCurrent])
NEXT
ELSE // Just return current
FOR nCurrent := 1 TO _SET_COUNT
aCurrentSets[nCurrent] := Set(nCurrent)
NEXT
ENDIF
RETURN (aCurrentSets)
Toggle asterisk (*) interpretation in the SetColor() string between blinking and background intensity
Syntax
SetBlink([<lToggle>]) → lCurrentSetting
Arguments
lToggle changes the meaning of the asterisk (*) character when it is encountered in a SetColor() string. Specifying true (.T.) sets character blinking on, and false (.F.) sets background intensity. The default is true (.T.).
Returns
SetBlink() returns the current setting as a logical value.
Description
SetBlink() is an environment function that toggles the blinking/background intensity attribute and reports the current state of SetBlink(). When SetBlink() is on, characters written to the screen can be made to blink by including an asterisk (*) in a color string passed to SetColor(). When SetBlink() is off, the asterisk (*) causes the background color to be intensified instead. Thus, blinking and background intensity attributes are not available at the same time.
Note: This function is meaningful only on the IBM PC or compatible computers with CGA, EGA, or VGA display hardware.
Examples
■ This example saves the current SetBlink() state before passing
control to a user-defined function. Upon return, SetBlink() is
restored to its original value:
lOldBlink := SetBlink()
MyFunc()
SetBlink(lOldBlink)
Toggle Alt+C and Ctrl+Break as program termination keys
Syntax
SetCancel([<lToggle>]) → lCurrentSetting
Arguments
lToggle changes the availability of Alt+C and Ctrl+Break as termination keys. Specifying true (.T.) allows either of these keys to terminate an application and false (.F.) disables both keys. The default is true (.T.).
Returns
SetCancel() returns the current setting as a logical value.
Description
SetCancel() is a keyboard function that toggles the state of the termination keys, Alt+C and Ctrl+Break, and reports the current state of SetCancel(). Use SetCancel() when you want to suppress a user's ability to terminate a program without using the specified method.
Note that if Alt+C or Ctrl+Break is redefined with SET KEY, the SET KEY definition takes precedence even if SetCancel() returns true (.T.).
Warning! When SetCancel() has been set to false (.F.), the user cannot terminate a runaway program unless you provide an alternative escape mechanism.
Examples
■ This example provides an escape route from a wait state with
SetCancel() set off:
#define K_ALTC 302
//
SetCancel(.F.) // Disable termination keys
SET KEY K_ALTC TO AltC // Redefine Alt-C
.
. <statements>
.
RETURN
FUNCTION AltC
LOCAL cScreen, nChoice, cLastColor := ;
SetColor("W/B, N/G")
//
SAVE SCREEN TO cScreen
@ 6, 20 CLEAR TO 9, 58
@ 6, 20 TO 9, 58 DOUBLE
@ 7, 26 SAY "Alt-C: Do you want to quit?"
@ 8, 35 PROMPT " Yes "
@ 8, 41 PROMPT " No "
MENU TO nChoice
SetColor(cLastColor)
RESTORE SCREEN FROM cScreen
//
IF nChoice = 1
QUIT
ENDIF
//
RETURN NIL
Return the current colors and optionally set new colors
Syntax
SetColor([<cColorString>]) → cColorString
Arguments
cColorString is a character string containing a list of color attribute settings for subsequent screen painting. The following is a list of settings and related scopes:
Color Settings
Setting Scope
Standard All screen output commands and functions
Enhanced GETs and selection highlights
Border Border around screen, not supported on EGA and VGA
Background Not supported
Unselected Unselected GETs
Each setting is a foreground and background color pair separated by the slash (/) character and followed by a comma. All settings are optional. If a setting is skipped, its previous value is retained with only new values set. Settings may be skipped within the list or left off the end as illustrated in the examples below.
Returns
SetColor() returns the current color settings as a character string.
Description
SetColor() is a screen function that saves the current color setting or sets new colors for subsequent screen painting. A color string is made from several color settings, each color corresponding to different regions of the screen. As stated above, each setting is made up of a foreground and background color. Foreground defines the color of characters displayed on the screen. Background defines the color displayed behind the character. Spaces and nondisplay characters display as background.
In CA-Clipper, the settings that define color behavior are:
Standard: The standard setting governs all console, full-screen, and interface commands and functions when displaying to the screen. This includes commands such as @...PROMPT, @...SAY, and ?, as well as functions such as AChoice(), dbEdit(), and MemoEdit().
Enhanced: The enhanced setting governs highlighted displays. This includes GETs with INTENSITY ON, and the MENU TO, dbEdit(), and AChoice() selection highlight.
Border: The border is an area around the screen that cannot be written to.
Background: The background is not supported.
Unselected: The unselected setting indicates input focus by displaying the current GET in the enhanced color while other GETs are displayed in the unselected color.
In addition to colors, foreground settings can have high intensity and/or blinking attributes. With a monochrome display, high intensity enhances brightness of painted text. With a color display, high intensity changes the hue of the specified color. For example, "N" displays foreground text as black where "N+" displays the same text as gray. High intensity is denoted by "+". The blinking attribute causes the foreground text to flash on and off at rapid intervals. Blinking is denoted with "*". The attribute character can occur anywhere in the setting string, but is always applied to the foreground color regardless where it occurs. See SetBlink() for additional information.
The following colors are supported:
List of Colors
Color Letter Monochrome
Black N, Space Black
Blue B Underline
Green G White
Cyan BG White
Red R White
Magenta RB White
Brown GR White
White W White
Gray N+ Black
Bright Blue B+ Bright Underline
Bright Green G+ Bright White
Bright Cyan BG+ Bright White
Bright Red R+ Bright White
Bright Magenta RB+ Bright White
Yellow GR+ Bright White
Bright White W+ Bright White
Black U Underline
Inverse Video I Inverse Video
Blank X Blank
Notes
■ Arguments are not specified: Unlike SET COLOR TO, SetColor()
with no argument does not restore colors to their default values.
■ Color numbers: SetColor() supports color letter combinations,
but not color number combinations.
Examples
■ This example assigns the current color setting to the
variable, cColor:
cColor:= SetColor()
■ This example uses SetColor() to save the current color setting
and set a new one.
cNewColor:= "BR+/N, R+/N"
cOldColor:= SetColor(cNewColor)
■ This example uses SET COLOR TO to reset the default colors:
SET COLOR TO
? SetColor() // Result: W/N, N/W, N, N, N/W
■ These two examples specify SetColor() with missing settings:
// Settings left off the end
SetColor("W/N, BG+/B")
//
// Settings skipped within the list
SetColor("W/N, BG+/B,,,W/N")
■ This example uses SetColor() with IsColor() to set the colors,
depending on the screen type:
FUNCTION DefaultColors
IF IsColor()
cForm := "W+/N, BG+/B,,,W/N"
cDialog := "N/N+, BG+/B,,,N/N+"
cAlert := "W+/R, BG+/B,,,W+/R"
ELSE
cForm := "W+/N, N/W,,,W/N"
cDialog := "W+/N, N/W,,,W/N"
cAlert := "W+/N, N/W,,,W/N"
ENDIF
RETURN NIL
nCursorShape is a number indicating the shape of the cursor. For simpler coding, the setcurs.ch header file provides descriptive names for the various cursor shapes as shown in the table below:
Cursor Shapes
Shape Value Setcurs.ch
None 0 SC_NONE
Underline 1 SC_NORMAL
Lower half block 2 SC_INSERT
Full block 3 SC_SPECIAL1
Upper half block 4 SC_SPECIAL2
Returns
SetCursor() returns the current cursor shape as a numeric value.
Description
SetCursor() is an environment function that controls the shape of the screen cursor. The actual shape is dependent on the current screen driver. The specified shapes appear on IBM PC and compatible computers. On other computers, the appearance may differ for each value specified.
SetCursor(0) is the same as SET CURSOR OFF, and any positive integer value of nCursorShape less than 5 is the same as SET CURSOR ON. The cursor will display as the selected shape.
Examples
■ This example uses SetCursor() to turn on a full block cursor
for the subsequent READ. When the READ terminates, SetCursor() turns
off the cursor:
#include "Setcurs.ch"
//
USE Customer NEW
@ 10, 10 GET Customer->Name
@ 11, 10 GET Customer->Phone
//
SetCursor(SC_SPECIAL1) // Change cursor to a block
READ
SetCursor(SC_NONE) // Turn off cursor
Platforms
Available on MS-DOS
File
Library is CLIPPER.LIB, header file is setcurs.ch.
nInkeyCode is the Inkey() value of the key to be associated or queried.
bAction specifies a code block that is automatically executed whenever the specified key is pressed during a wait state.
Returns
SetKey() returns the action block currently associated with the specified key, or NIL if the specified key is not currently associated with a block.
Description
SetKey() is a keyboard function that sets or queries the automatic action associated with a particular key during a wait state. A wait state is any mode that extracts keys from the keyboard except for Inkey(), but including AChoice(), dbEdit(), MemoEdit(), ACCEPT, INPUT, READ and WAIT. Up to 32 keys may be assigned at any one time. At startup, the system automatically assigns the F1 key to execute a procedure or user-defined function named Help.
When an assigned key is pressed during a wait state, the Eval() function evaluates the associated bAction and the parameters, ProcName(), ProcLine(), and ReadVar(). It is, however, not necessary to list arguments when specifying bAction if you do not plan to use them within the action block.
SetKey() is like the SET KEY command which associates a procedure invocation with a key.
Examples
■ This code fragment associates an action block with a key, and
then, after getting a key using Inkey(), executes it with the Eval()
function:
#include "Inkey.ch"
SetKey(K_DN, {|cProc, nLine, cVar| MyProc(cProc, ;
nLine, cVar)})
.
. <statements>
.
DO WHILE .T.
nKey := Inkey(0)
DO CASE
CASE (bAction := SetKey(nKey)) != NIL
Eval(bAction, ProcName(), ProcLine(), ReadVar())
CASE nKey = K_PGUP
Previous()
CASE nKey = K_PGDN
Next()
CASE nKey = K_ESC
EXIT
ENDCASE
ENDDO
Change display mode to a specified number of rows and columns
Syntax
SetMode(<nRows>, <nCols>) → lSuccess
Arguments
nRows is the number of rows in the desired display mode.
nCols is the number of columns in the desired display mode.
Returns
SetMode() returns true (.T.) if the mode change was successful; otherwise, it returns false (.F.).
Description
SetMode() is an environment function that attempts to change the mode of the display hardware to match the number of rows and columns specified. The change in screen size is reflected in the values returned by MaxRow() and MaxCol().
Note: In LLG_VIDEO_TXT mode, and when a VESA driver is present, it is possible to use the following values : 25,80 | 43,80 | 50,80 | 60,80 | 25,132 | 43,132 | 50,132 | 60,132
Examples
■ This example switches to a 43-line display mode:
IF SetMode(43, 80)
? "43-line mode successfully set"
ELSE
? "43-line mode not available"
ENDIF
■ This example switches the video mode to regular text mode with
60 rows and 132 columns:
// Switch to text mode
SET VIDEOMODE( LLG_VIDEO_TXT )
// Set the video mode to the largest number of characters
SetMode( 60,132 )
nRow and nCol define the new screen position of the cursor. These values may range from 0, 0 to MaxRow(), MaxCol().
Returns
SetPos() always returns nRow
Description
SetPos() is an environment function that moves the cursor to a new position on the screen. After the cursor is positioned, Row() and Col() are updated accordingly. To control the shape and visibility of the cursor, use the SetCursor() function.
Examples
■ This example moves the cursor to a new position then displays
a string to the screen using a console command, ??:
SetPos(1, 1)
?? "Hello world"
SetPRC() is a printer function that sends control codes to the printer without changing the tracking of the printhead position. When CA-Clipper prints, it updates the PCol() value with the number of characters sent to the printer. There is no discrimination between printable or nonprintable characters. If, for example, a string of ten characters sent to the printer contains two characters interpreted by the printer as a control code, the CA-Clipper PCol() value is incremented by ten, while the true printhead position is moved only by eight. This can lead to alignment problems. Using SetPRC(), you can compensate for control codes by resetting PCol() as shown in the example below.
SetPRC() also suppresses page ejects when printing with @...SAY. This is important when the next row position is smaller than the current row and an EJECT has not been issued. In this situation, CA-Clipper issues an automatic page eject if the next row print position is less than the current PRow() value. Using SetPRC(), you can set PRow() to a number less than the current row, thus suppressing the automatic EJECT.
Examples
■ This user-defined function, PrintCodes(), uses SetPRC() to
send control codes to the printer without affecting PRow() and PCol()
values:
#include "Set.ch"
#define ITALICS_ON Chr(27) + "I"
#define ITALICS_OFF Chr(27) + "E"
//
SET DEVICE TO PRINTER
@ 12, 10 SAY "This is an"
@ PRow(), PCol() + 2 SAY PrintCodes(ITALICS_ON) + ;
"important"
@ PRow(), PCol() + 2 SAY PrintCodes(ITALICS_OFF) + ;
"meeting"
SET DEVICE TO SCREEN
RETURN
FUNCTION PrintCodes( cCtrlCode )
LOCAL nRow, nCol, lPrinter
lPrinter := Set(_SET_PRINTER, .T.) // SET PRINTER ON
nRow:= PRow() // Save printhead position
nCol:= PCol()
//
?? cCtrlCode // Send control code
//
SetPRC(nRow, nCol)
Set(_SET_PRINTER, lPrinter) // Restore printer setting
RETURN "" // Return a null string
expSearch is an expression to match with an order key value.
SOFTSEEK causes the record pointer to be moved to the next record with a higher key value after a failed order search. Default behavior moves the record pointer to Eof() after a failed order search.
Description
SEEK is a database command that searches the controlling order from the first or last key value (depending on whether the LAST keyword is specified) and proceeds until a match is found or there is a key value greater than expSearch. If there is a match, the record pointer is positioned to the identity found in the order. If SOFTSEEK is OFF (the default) and SEEK does not find a match, the record pointer is positioned to LastRec() + 1, Eof() returns true (.T.), and Found() returns false (.F.).
SOFTSEEK enables a method of searching an order and returning a record even if there is no match for a specified key.
When SOFTSEEK is ON and a match for a SEEK is not found, the record pointer is set to the next record in the order with a higher key value than the SEEK argument. Records are not visible because SET FILTER and/or SET DELETED are skipped when searching for the next higher key value. If there is no record with a higher key value, the record pointer is positioned at LastRec() + 1, Eof() returns true (.T.), and Found() returns false (.F.). Found() returns true (.T.) only if the record is actually found. Found() never returns true (.T.) for a relative find.
When SOFTSEEK is OFF and a SEEK is unsuccessful, the record pointer is positioned at LastRec() + 1, Eof() returns true (.T.), and Found() returns false (.F.).
SEEK with the SOFTSEEK clause is, effectively, the same as performing SET SOFTSEEK and then SEEK in earlier versions of CA-Clipper except that it does not change the global setting of SOFTSEEK.
Examples
■ The following example searches for "Doe" using the SEEK
command:
USE Customer NEW
SET ORDER TO Customer
? Set( _SET_SOFTSEEK ) // (.F.)
SEEK "Doe"
? Set( _SET_SOFTSEEK ) // Still (.F.)
IF Found()
.
. < statements >
.
ENDIF
■ The following example performs a soft seek for "Doe" using
SOFTSEEK clause of the SEEK command:
USE Customer NEW
SET ORDER TO Customer
? Set( _SET_SOFTSEEK ) // (.F.)
SEEK "Doe" SOFTSEEK
? Set( _SET_SOFTSEEK ) // Still (.F.)
IF !Found()
? Customer->Name // Returns next logical name after "Doe"
ENDIF
xnWorkArea is the work area number between 0 and 250 inclusive. This argument is an extended expression and can be specified either as a literal number or as a numeric expression enclosed in parentheses.
idAlias is the name of an existing work area to SELECT if there is a database file open in that area.
Description
SELECT is a database command that changes work areas. CA-Clipper supports 250 work areas, with each work area a logical handle to an open database file and all of its attributes. You can refer to work areas with SELECT by number or by alias. The alias of a work area is automatically assigned when a database file is USEd in that work area or by using the ALIAS clause.
Work area 0 refers to the first empty or next available work area. Using this, you can SELECT 0 and USExcDatabase as a method of opening database files.
Notes
■ Aliased expressions: Aliased expressions are a much more
powerful method of selecting new work areas than the SELECT command. Instead of SELECTing a work area, and then performing an operation for that work area, you can apply an alias to an expression that performs the operation. This is done by specifying the alias of the remote work area and the expression enclosed in parentheses. For example, to access the value of Eof() in an unselected work area, you would normally execute a series of statements like the following:
■ USE...NEW: Instead of using SELECT0 and USExcDatabase to
open a database file in a new work area, the preferred method is to USExcDatabaseNEW.
Examples
■ This example opens a series of database files by SELECTing
each work area by number then USEing each database file in that work
area:
SELECT 1
USE Customer
SELECT 2
USE Invoices
SELECT 3
USE Parts
SELECT Customer
■ A better method is to open each database in the next available
work area by specifying the NEW clause on the USE command line. In
this example USE...NEW is employed instead of SELECT0 and then USE:
USE Customer NEW
USE Invoices NEW
SELECT Customer
■ This code fragment changes work areas while saving the current
work area name to a variable using the Select() function. After
executing an operation for the new work area, the original work area
is restored:
nLastArea := Select()
USE Newfile NEW
//
<statements>...
//
SELECT (nLastArea)
SET ALTERNATE TO [<xcFile> [ADDITIVE]]
SET ALTERNATE on | OFF | <xlToggle>
Arguments
TOxcFile opens a standard ASCII text file for output with a default extension of .txt. The file name may optionally include an extension, drive letter, and/or path. You may specify xcFile either as a literal file name or as a character expression enclosed in parentheses. Note that if a file with the same name exists, it is overwritten.
ADDITIVE causes the specified alternate file to be appended instead of being overwritten. If not specified, the specified alternate file is truncated before new information is written to it.
ON causes console output to be written to the open text file.
OFF discontinues writing console output to the text file without closing the file.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
SET ALTERNATE is a console command that lets you write the output of console commands to a text file. Commands such as LIST, REPORT FORM, LABEL FORM, and ? that display to the screen without reference to row and column position are console commands. Most of these commands have a TO FILE clause that performs the same function as SET ALTERNATE. Full- screen commands such as @...SAY cannot be echoed to a disk file using SET ALTERNATE. Instead you can use SET PRINTER TOxcFile with SET DEVICE TO PRINTER to accomplish this.
SET ALTERNATE has two basic forms. The TOxcFile form creates a DOS text file with a default extension of .txt and overwrites any other file with the same name. Alternate files are not related to work areas with only one file open at a time. To close an alternate file, use CLOSE ALTERNATE, CLOSE ALL, or SET ALTERNATE TO with no argument.
The on|OFF form controls the writing of console output to the current alternate file. SET ALTERNATE ON begins the echoing of output to the alternate file. SET ALTERNATE OFF suppresses output to the alternate file but does not close it.
Examples
■ This example creates an alternate file and writes the results
of the ? command to the file for each record in the Customer database
file:
SET ALTERNATE TO Listfile
SET ALTERNATE ON
USE Customer NEW
DO WHILE !Eof()
? Customer->Lastname, Customer->City
SKIP
ENDDO
SET ALTERNATE OFF
CLOSE ALTERNATE
CLOSE Customer
Toggle automatic sounding of the bell during full-screen operations
Syntax
SET BELL on | OFF | <xlToggle>
Arguments
ON enables the BELL.
OFF disables the BELL.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
SET BELL is an environment command that toggles the sound of the bell. If SET BELL is ON, the bell sounds in the following situations:
■ The user enters a character at the last position in a GET.
■ The user attempts to enter invalid data into a GET. The data
is validated by the data type of the GET variable, the PICTURE template, and by the RANGE clause. Violating a VALID condition does not sound the bell, regardless of the SET BELL status.
To sound the bell explicitly, you can use either ?? Chr(7) or the Tone() function. Tone() is perhaps more useful since you can vary both the pitch and duration of the sound.
Modify the date format to include or omit century digits
Syntax
SET CENTURY on | OFF | <xlToggle>
Arguments
ON allows input and display of the century digits for dates.
OFF suppresses the input and display of the century digits for dates.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
SET CENTURY modifies the current date format as set by SET DATE. SET CENTURY ON changes the date format to contain four digits for the year. With the date format set to four digits for the year, date values display with a four-digit year, and dates of any century can be input.
SET CENTURY OFF changes the date format to contain only two digits for the year. With the date format set to only two digits for the year (CENTURY OFF), the century digits of dates are not displayed and cannot be input.
Note that only the display and input format of dates is affected; date calculations maintain the century information regardless of the date format.
CA-Clipper supports all dates in the range 01/01/0100 to 12/31/2999.
Examples
■ This example shows the results of a simple SET CENTURY
command:
SET CENTURY OFF
? Date() // Result: 09/15/90
SET CENTURY ON
? Date() // Result: 09/15/1990
SET COLOR | COLOUR TO [[<standard>]
[,<enhanced>] [,<border>] [,<background>]
[,<unselected>]] | (<cColorString>)
Arguments
standard is the color that paints all console, full-screen, and interface commands and functions when displaying to the screen. This includes commands such as @...PROMPT, @...SAY, and ?; as well as functions such as AChoice(), dbEdit(), and MemoEdit().
enhanced is the color that paints highlighted displays. This includes GETs with INTENSITY ON, the MENU TO, dbEdit(), and AChoice() selection highlight.
border is the color that paints the area around the screen that cannot be written to.
background is not currently supported by any machines for which Computer Associates provides drivers. This setting is supplied for compatibility purposes only.
unselected is a color pair that provides input focus by displaying the current GET in the enhanced color while other GETs are displayed in this color.
cColorString is a character string enclosed in parentheses containing the color settings. This facility lets you specify the color settings as an expression in place of a literal string or macro variable.
SET COLOR TO with no argument restores the default colors to W/N, N/W, N, N, N/W.
Description
SET COLOR, a command synonym for the SetColor() function, defines colors for subsequent screen painting activity. Each SET COLOR command specifies a list of color settings for the five types of screen painting activity. Each setting is a foreground and background color pair separated by the slash (/) character. Foreground defines the color of characters displayed on the screen. Background defines the color displayed behind the character. Spaces and nondisplay characters display as background only.
In addition to color, a foreground setting can have an attribute, high intensity or blinking. With a monochrome display, high intensity enhances brightness of painted text. With a color display, high intensity changes the hue of the specified color making it a different color. For example, N displays foreground text as black where N+ displays the same text as gray. High intensity is denoted by +. The blinking attribute causes the foreground text to flash on and off at a rapid interval. Blinking is denoted with *. An attribute character can occur anywhere in a setting, but is always applied to the foreground color regardless where it occurs.
Each color can be specified using either a letter or a number, but numbers and letters cannot be mixed within a setting. Note that numbers are supplied for compatibility purposes and are not recommended.
All settings are optional. If a setting is skipped, its previous value is retained with only new values set. Skipping a foreground or background color within a setting sets the color to black.
The following colors are supported:
Color Table
Color Letter Number Monochrome
Black N, Space 0 Black
Blue B 1 Underline
Green G 2 White
Cyan BG 3 White
Red R 4 White
Magenta RB 5 White
Brown GR 6 White
White W 7 White
Gray N+ 8 Black
Bright Blue B+ 9 Bright Underline
Bright Green G+ 10 Bright White
Bright Cyan BG+ 11 Bright White
Bright Red R+ 12 Bright White
Bright Magenta RB+ 13 Bright White
Yellow GR+ 14 Bright White
Bright White W+ 15 Bright White
Black U Underline
Inverse Video I Inverse Video
Blank X Blank
SET COLOR is a compatibility command and is not recommended. It is superseded by the SetColor() function which can return the current color as well as set a new color.
Notes
■ Monochrome monitors: Color is not supported on monochrome
monitors. CA-Clipper, however, supports the monochrome attributes inverse video (I) and underlining (U).
■ Screen drivers: SET COLOR TO, using numbers, may not be
supported by screen drivers other than the default screen driver.
Examples
■ This example uses the unselected setting to make the current
GET red on white while the rest are black on white:
cColor:= "W/N,R/W,,,N/W"
SET COLOR TO (cColor)
cOne := cTwo := Space(10)
@ 1, 1 SAY "Enter One: " GET cOne
@ 2, 1 SAY "Enter Two: " GET cTwo
READ
■ In this example a user-defined function gets a password from
the user using the blank (X) enhanced setting to hide the password as
the user types:
IF !DialogPassWord(12, 13, "W+/N", "FUNSUN", 3)
? "Sorry, your password failed"
QUIT
ENDIF
FUNCTION DialogPassWord( nRow, nCol, ;
cStandard, cPassword, nTries )
LOCAL nCount := 1, cColor := SetColor()
SET COLOR TO (cStandard + ", X") // Blank input
//
DO WHILE nCount < nTries
cUserEntry:= Space(6)
@ nRow, nCol SAY "Enter password: " GET ;
cUserEntry
READ
//
IF LastKey() == 27
SET COLOR TO (cColor)
RETURN .F.
ELSEIF cUserEntry == cPassword
SET COLOR TO (cColor)
RETURN .T.
ELSE
nCount++
ENDIF
ENDDO
//
SET COLOR TO (cColor)
RETURN .F.
ON requires the user to press an exit key to leave a GET.
OFF allows the user to leave a GET by typing past the end without pressing an exit key.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
SET CONFIRM determines whether an exit key is required to leave a GET. If CONFIRM is OFF, the user can type past the end of a GET and the cursor will move to the next GET, if there is one. If there is not another GET, the READ terminates. If, however, CONFIRM is ON, an exit key must be pressed to leave the current GET.
In all cases, attempting to leave the current GET executes the RANGE or VALID clauses, unless the user presses the Esc key.
See @...GET for more information on the behavior of GETs.
ON displays the output of console commands on the screen.
OFF suppresses the screen display of console commands.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
SET CONSOLE determines whether or not console commands send output to the screen. Console commands are commands that display to the screen without reference to row and column position. In addition to sending output to the screen, console commands can simultaneously send output to the printer and/or a DOS text file. Output is sent to the printer using the TO PRINTER clause common to many console commands, or with the SET PRINTER ON command. Output is sent to a file using the TO FILE clause, SET ALTERNATE, or SET PRINTER TO.
With CONSOLE ON, console commands display to the screen. With CONSOLE OFF, the screen display of console commands is suppressed, but the echoing of output to either a file or the printer is unaffected. This lets you send the output of console commands such as REPORT and LABEL FORM to the printer without the screen display—a common occurrence.
Notes
■ Keyboard input: For console commands that accept input
(including ACCEPT, INPUT, and WAIT), SET CONSOLE affects the display of the prompts as well as the input areas. As a consequence, a SET CONSOLE OFF before one of these commands will not only prevent you from seeing what you type, but will also prevent the display of the message prompt.
■ Full-screen commands: Full-screen commands such as @...SAY
display to the screen independent of the current CONSOLE SETting. For this category of output commands, device control is performed using SET DEVICE to control whether output goes to the screen or printer, and SET PRINTER TO echo output to a file.
Examples
■ This example uses REPORT FORM to output records to the printer
while suppressing output to the screen:
USE Sales NEW
SET CONSOLE OFF
REPORT FORM Sales TO PRINTER
SET CONSOLE ON
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
SET CURSOR toggles the screen cursor on or off. When the CURSOR is OFF, keyboard entry and screen display are unaffected. The cursor is merely hidden and data entry may still be accomplished without the cursor being visible. Row() and Col() are updated as if the cursor were visible.
This command suppresses the cursor while the screen is being painted. Ideally, the only time the cursor shows in a production program is when the user is editing GETs, MemoEdit(), or some kind of line edit.
Examples
■ This example shows a typical use of SET CURSOR:
LOCAL lAnswer := .F.
@ 24, 0
@ 24, 15 SAY "Do you want to QUIT? [Y/N]";
GET lAnswer;
PICTURE "Y"
SET CURSOR ON
READ
SET CURSOR OFF
SET DATE FORMAT [TO] <cDateFormat>
SET DATE [TO] AMERICAN | ansi | British | French
| German | Italian | Japan | USA
Arguments
cDateFormat is a character expression that directly specifies the date format when the FORMAT clause is specified. cDateFormat must evaluate to a string of 12 or fewer characters.
When specified, cDateFormat is analyzed to determine the proper placement and number of digits for the day, month, and year. The position of the day, month, and year digits is determined by scanning the string for one or more occurrences of the letters d, m, and y, respectively. Other characters in the string are copied verbatim into displayed date values.
When FORMAT is not used, one of several keywords describes the date format. The following table shows the format for each keyword setting:
SET DATE Formats
SETting Format
AMERICAN mm/dd/yy
ANSI yy.mm.dd
BRITISH dd/mm/yy
FRENCH dd/mm/yy
GERMAN dd.mm.yy
ITALIAN dd-mm-yy
JAPAN yy/mm/dd
USA mm-dd-yy
Description
SET DATE is an environment command that sets the display format for date values. SET DATE is a global setting that affects the behavior of dates throughout a program, allowing you to control date formatting in a way that facilitates porting applications to foreign countries.
Examples
■ In this example the FORMAT clause directly specifies the date
format:
SET DATE FORMAT "yyyy:mm:dd"
■ This example configures the date setting at runtime by passing
a DOS environment variable to the program, retrieving its value with
GetEnv(), and setting DATE with the retrieved value:
C>SET CLIP_DATE=dd/mm/yy
In the configuration section of the application program, the date
format is set like this:
FUNCTION AppConfig
SET DATE FORMAT TO GetEnv("CLIP_DATE")
RETURN NIL
TOnDecimals is the number of decimal places to be displayed. The default value is two.
SET DECIMALS TO with no argument is equivalent to SET DECIMALS TO 0.
Description
SET DECIMALS determines the number of decimal places displayed in the results of numeric functions and calculations. Its operation depends directly on the FIXED setting. If FIXED is OFF, SET DECIMALS establishes the minimum number of decimal digits displayed by Exp(), Log(), Sqrt(), and division operations. If FIXED is ON, all numeric values are displayed with exactly the number of decimal places specified by SET DECIMALS. Note that neither SET DECIMALS nor SET FIXED affects the actual numeric precision of calculations—only the display format is affected.
To provide finer control of numeric display, you can use the PICTURE clause of @...SAY, @...GET, and the Transform() function.
Examples
■ These examples show various results of the SET DECIMALS
command:
SET FIXED ON
SET DECIMALS TO 2 // The default setting
? 2/4 // Result: 0.50
? 1/3 // Result: 0.33
SET DECIMALS TO 4
? 2/4 // Result: 0.5000
? 1/3 // Result: 0.3333
TOxcPathspec identifies a disk drive and the directory as the default and can be specified either as a literal path specification or as a character expression enclosed in parentheses. If you specify both a drive and directory, a colon must be included after the drive letter.
SET DEFAULT TO specified without an argument defaults to the current DOS drive and directory.
Description
SET DEFAULT sets the drive and directory where the application program creates and saves files, with the exception of temporary files and files created with the low-level file functions.
SET DEFAULT does not change the DOS drive and directory. When attempting to access files, the DEFAULT drive and directory are searched first. To set additional search paths for file access, use SET PATH.
Notes
■ Initial Default: When a CA-Clipper program starts, the default
drive and directory are the current DOS drive and directory. Within the program, you can change this with SET DEFAULT.
■ Running external programs: Executing a RUN command accesses
the current DOS drive and directory.
Examples
■ This example shows a typical use of SET DEFAULT:
SET PATH TO
? FILE("Sales.dbf") // Result: .F.
//
SET DEFAULT TO C:\CLIPPER\FILES
? FILE("Sales.dbf") // Result: .T.
//
SET DEFAULT TO C: // Change default drive
SET DEFAULT TO \ // Change to root directory
SET DEFAULT TO .. // Change to parent directory
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
SET DELETED toggles automatic filtering of records marked for deletion in all work areas. When SET DELETED is ON, most commands ignore deleted records. If, however, you refer to a record by record number (GOTO or any command that supports the RECORD scope), the record is not ignored even if marked for deletion. Additionally, SET DELETED ON has no affect on INDEX or REINDEXing.
RECALL ALL honors SET DELETED and does not recall any records.
Notes
■ Filtering deleted records in a single work area: To confine
the filtering of deleted records to a particular work area, SELECT the work area, and then SET FILTER TODeleted().
Examples
■ This example illustrates the effect of using SET DELETED:
USE Sales NEW
? LastRec() // Result: 84
//
DELETE RECORD 4
COUNT TO nCount
? nCount // Result: 84
//
SET DELETED ON
COUNT TO nCount
? nCount // Result: 83
SET DELIMITERS on | OFF | <xlToggle>
SET DELIMITERS TO [<cDelimiters> | DEFAULT]
Arguments
ON displays delimiters for GET variables.
OFF suppresses the delimiter display.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
TOcDelimiters defines a one or two character delimiter. Specifying a single character uses the same character as both the beginning and ending delimiter. Specifying two characters uses the first as the beginning delimiter and the second as the ending delimiter.
TO DEFAULT or no delimiters SETs the delimiters to colons which are the default delimiters.
Description
SET DELIMITERS is a dual purpose command that both defines characters used to delimit GETs and toggles the automatic display of delimiters ON or OFF. The @...GET command can display delimiters that surround a Get object's display. If DELIMITERS is ON, the delimiters add two characters to the length of the Get object display.
You can configure the delimiter characters using the TOcDelimiters clause. The DEFAULT delimiter character is the colon (:). When specifying delimiters, the beginning and ending delimiter characters can be different. If you wish to suppress either the right, left, or both delimiters, use a space instead of the delimiter character.
Typically, delimiters are unnecessary since GETs display in reverse video or enhanced color if INTENSITY is ON.
Examples
■ This example SETs DELIMITERS TO a colon and a space for the
first GET and the square bracket characters for the second:
LOCAL cVar := Space(5), cVar2 := Space(5)
SET DELIMITERS ON
SET DELIMITERS TO ": "
@ 1, 0 SAY "Enter" GET cVar
SET DELIMITERS TO "[]"
@ 2, 0 SAY "Enter" GET cVar2
READ
Change the descending flag of the controlling order
Syntax
SET DESCENDING ON | OFF | (<lToggle>)
Arguments
ON enables the descending flag.
OFF disables the descending flag.
lToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Note: The initial default of this setting depends on whether the controlling order was created with DESCENDING as an attribute.
Description
SET DESCENDING is functionally equivalent to ordDescend(). Refer to this function for more information.
Examples
■ The following example illustrates SET DESCENDING. every order
can be both ascending and descending:
USE Customer VIA "DBFCDX"
INDEX ON LastName TAG Last
INDEX ON FirstName TAG First DESCENDING
SET ORDER TO TAG Last
// last was originally created in ascending order
// Swap it to descending
SET DESCENDING ON
// Last will now be processed in descending order
SET ORDER TO TAG First
// First was originally created in descending order
// Swap it to ascending
SET DESCENDING OFF
// First will now be processed in ascending order
TO SCREEN directs all @...SAYs to the screen and is independent of the SET PRINTER and CONSOLE settings.
TO PRINTER directs all @...SAYs to the device set with SET PRINTER TO. This can include a local printer port, a network spooler, or a file.
Description
SET DEVICE directs the output of @...SAY commands to either the screen or the printer. When DEVICE is SET TO PRINTER, @...SAY commands are sent to the printer and not echoed to the screen. In addition, @...SAY commands observe the current SET MARGIN value.
When sending @...SAYs to the printer, CA-Clipper performs an automatic EJECT whenever the current printhead row position is less than the last print row position. An EJECT resets PCol() and PRow() values to zero. To reset PCol() and PRow() to new values, use the SetPRC() function.
To send @...SAYs to a file, use SET PRINTER TOxcFile with SET DEVICE TO PRINTER.
Examples
■ This example directs @...SAYs to the printer:
SET DEVICE TO PRINTER
@ 2,10 SAY "Hello there"
EJECT
■ This example directs @...SAYs to a file:
SET PRINTER TO Output.txt
SET DEVICE TO PRINTER
@ 10, 10 SAY "File is: Output.txt"
@ 11, 10 SAY Date()
SET PRINTER TO // Close the output file
SET DEVICE TO SCREEN
Control the interpretation of dates with no century digits
Syntax
SET EPOCH TO <nYear>
Arguments
TOnYear specifies the base year of a 100-year period in which all dates containing only two year digits are assumed to fall.
Description
SET EPOCH is an environment command that determines the interpretation of date strings containing only two year digits. When such a string is converted to a date value, its year digits are compared with the year digits of nYear. If the year digits in the date are greater than or equal to the year digits of nYear, the date is assumed to fall within the same century as nYear. Otherwise, the date is assumed to fall in the following century.
The default value for SET EPOCH is 1900, causing dates with no century digits to be interpreted as falling within the twentieth century.
CA-Clipper supports all dates in the range 01/01/0100 to 12/31/2999.
Examples
■ This example shows the effects of SET EPOCH:
SET DATE FORMAT TO "mm/dd/yyyy"
? CToD("05/27/1904") // Result: 05/27/1904
? CToD("05/27/67") // Result: 05/27/1967
? CToD("05/27/04") // Result: 05/27/1904
//
SET EPOCH TO 1960
? CToD("05/27/1904") // Result: 05/27/1904
? CToD("05/27/67") // Result: 05/27/1967
? CToD("05/27/04") // Result: 05/27/2004
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
If SET ESCAPE is ON, Esc terminates the current READ. Any changes made to the current Get object are lost, and validation with RANGE or VALID is bypassed. When SET ESCAPE is OFF and the user presses Esc, the key press is ignored. With SET KEY, however, you can reassign Esc for special handling, regardless of the status of SET ESCAPE.
Specify events to be returned by the Inkey() function
Syntax
SET EVENTMASK TO <nEventMask>
Arguments
nEventMask specifies which events should be returned by the Inkey() function. This argument can be any combination of the following values which are defined in inkey.ch:
Inkey Constants
Constant Value Description
INKEY_MOVE 1 Mouse Events
INKEY_LDOWN 2 Mouse Left Click Down
INKEY_LUP 4 Mouse Left Click Up
INKEY_RDOWN 8 Mouse Right Click Down
INKEY_RUP 16 Mouse Right Click Up
INKEY_KEYBOARD 128 Keyboard Events
INKEY_ALL 159 All Mouse and Keyboard Events
If a value is not specified for SET EVENTMASK, the default value of 128 (keyboard events only) will be used.
Description
The SET EVENTMASK command specifies which events should be returned by the Inkey() function. Using this mask you can have Inkey() return only the events in which you are interested.
Examples
The following example will inform Inkey() to terminate if a keyboard
event occurs or the left mouse button has been clicked. If no events
occur within 5 seconds, Inkey() will terminate.
SET EVENTMASK TO INKEY_KEYBOARD + INKEY_LDOWN
? Inkey( 5 )
ON enforces exact comparison of character strings including length.
OFF resumes normal character string comparison.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
SET EXACT determines how two character strings are compared using the relational operators (=, >, , =, =`). When EXACT is OFF, strings are compared according to the following rules. assume two character strings cLeft and cRight where the expression to test is (cLeft = cRight):
■ If cRight is a null string (""), return true (.T.).
■ If Len(cRight) is greater than Len(cLeft), return false (.F.).
■ Otherwise, compare all characters in cRight with cLeft. If
all characters in cRight equal cLeft, return true (.T.); otherwise, return false (.F.).
With EXACT ON, all relational operators except the double equal operator (==) treat two strings as equal, if they match exactly, excluding trailing spaces. With the double equal operator (==), all characters in the string are significant, including trailing spaces.
SET EXACT is a compatibility command and not recommended.
Notes
■ Compatibility: In CA-Clipper, unlike other dialects, SET EXACT
has no affect on operations other than relational operators. This includes the SEEK and FIND commands. If you need to seek exact matches of character keys, use the example user-defined function SeekExact() in the SEEK command reference.
Examples
■ These examples show various results of the equal operator (=)
with SET EXACT:
SET EXACT OFF
? "123" = "12345" // Result: .F.
? "12345" = "123" // Result: .T.
? "123" = "" // Result: .T.
? "" = "123" // Result: .F.
? "123" = "123 " // Result: .F.
//
SET EXACT ON
? "123" = "12345" // Result: .F.
? "12345" = "123" // Result: .F.
? "123" = "" // Result: .F.
? "" = "123" // Result: .F.
? "123" = "123 " // Result: .T.
Establish shared or exclusive USE of database files
Syntax
SET EXCLUSIVE ON | off | <xlToggle>
Arguments
ON causes database files to be opened in exclusive (nonshared) mode.
OFF causes database files to be opened in shared mode.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
In a network environment, SET EXCLUSIVE determines whether a USE command specified without the EXCLUSIVE or SHARED clause automatically opens database, memo, and index files EXCLUSIVE. When database files are opened EXCLUSIVE, other users cannot USE them until they are CLOSEd. In this mode, file and record locks are unnecessary.
When EXCLUSIVE is ON (the default), all database and associated files open in a nonshared (exclusive) mode unless the USE command is specified with the SHARED clause. Use EXCLUSIVE only for operations that absolutely require EXCLUSIVE USE of a database file, such as PACK, REINDEX, and ZAP.
When EXCLUSIVE is OFF, all files are open in shared mode unless the USE command is specified with the EXCLUSIVE clause. Control access by other users programmatically using RLock() and FLock().
SET EXCLUSIVE is a compatibility command and not recommended. It is superseded by the EXCLUSIVE and SHARED clauses of the USE command.
Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information.
Notes
■ Error handling: Attempting to USE a database file already
opened EXCLUSIVE by another user generates a runtime error and sets NetErr() to true (.T.). After control returns to the point of error, you can test NetErr() to determine whether the USE failed.
TOlCondition is a logical expression that defines a specific set of current work area records accessible for processing.
SET FILTER TO without an argument deactivates the filter condition.
Description
When a FILTER condition is SET, the current work area acts as if it contains only the records that match the specified condition. A filter condition is one of the properties of a work area. Once a FILTER has been SET, the condition can be returned as a character string using the dbFilter() function.
Most commands and functions that move the record pointer honor the current filter with the exception of those commands that access records by record number. This includes GOTO, commands specified with the RECORD clause, and RELATIONs linked by numeric expression to a work area with no active index.
Once a FILTER is SET, it is not activated until the record pointer is moved from its current position. You can use GO TOP to activate it.
As with SET DELETED, a filter has no effect on INDEX and REINDEX.
Note: Although SET FILTER makes the current work area appear as if it contains a subset of records, it, in fact, sequentially processes all records in the work area. Because of this, the time required to process a filtered work area will be the same as an unfiltered work area.
Examples
■ This example filters Employee.dbf to only those records where
the age is greater than 50:
USE Employee INDEX Name NEW
SET FILTER TO Age > 50
LIST Lastname, Firstname, Age, Phone
SET FILTER TO
Toggle fixing of the number of decimal digits displayed
Syntax
SET FIXED on | OFF | <xlToggle>
Arguments
ON fixes the decimal places display at the number of digits specified by SET DECIMALS.
OFF allows the operation or function to determine the number of decimal places to display.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
SET FIXED toggles control of the display of decimal digits by the current DECIMALS setting. When FIXED is ON, display of all numeric output is fixed at the DECIMALS setting (two places if the SET DECIMALS default value is in effect). When FIXED is OFF, numeric output displays according to the default rules for numeric display. These are described in the "Basic Concepts" chapter of the Programming and Utilities Guide.
Note that SET FIXED and SET DECIMALS affect only the display format of numeric values and not the actual numeric precision of calculations.
TOidProcedure is a format (.fmt) file, a program (.prg) file, or a procedure.
ext is the extension of the format file. If not specified, the default extension is (.fmt).
SET FORMAT TO with no argument deactivates the current format.
Description
SET FORMAT defines a procedure to execute when a READ is invoked. Unlike the interpreted environment, formats are not opened and executed at runtime. Instead, the CA-Clipper compiler treats SET FORMAT the same as a DO command. The compiler first looks to see whether it has already compiled a procedure with the same name as idProcedure. If it has, it uses that procedure for the reference. If idProcedure is not found, the compiler looks to disk for a file with the same name. If this file is not found, an external reference is generated that must be resolved at link time.
SET FORMAT is a compatibility command and not recommended.
Notes
■ Active format procedures: Unlike other dialects where each
work area can have an active format, CA-Clipper supports only one active format procedure for all work areas.
■ Screen CLEARing: CA-Clipper does not clear the screen when a
format procedure is executed.
■ Legal statements: Format procedures allow statements and
commands in addition to @...SAY and @...GET.
■ Multiple pages: CA-Clipper does not support multiple-page
format procedures.
Examples
■ This example uses a format procedure to add records to a
database file until the user presses Esc:
USE Sales NEW
SET FORMAT TO SalesScr
DO WHILE LastKey() != 27
APPEND BLANK
READ
ENDDO
RETURN
PROCEDURE SalesScr
@ 12, 12 SAY "Branch : " GET Branch
@ 13, 12 SAY "Salesman : " GET Salesman
RETURN
nFunctionKey is the number of the function key to receive the assignment.
TOcString specifies the character string to assign to nFunctionKey.
Description
SET FUNCTION assigns a character string to a function key numbered between 1 and 40 inclusive. When the user presses the assigned function key, cString is stuffed into the keyboard buffer. cString can include control characters, such as a Ctrl+C or Ctrl+S to perform navigation or editing actions in a wait state.
List of Function Key Mappings
Function Key Actual Key
1 - 10 F1 - F10
11 - 20 Shift+F1 - Shift+F10
21 - 30 Ctrl+F1 - Ctrl+F10
31 - 40 Alt+F1 - Alt+F10
Warning! In CA-Clipper, SET FUNCTION is preprocessed into SET KEY and KEYBOARD commands. This means that SET FUNCTION has the effect of clearing any SET KEY for the same key number and vice versa. This is incompatible with previous releases, which maintained separate lists of SET FUNCTION keys and SET KEY keys.
Open one or more order bags in the current work area
Syntax
SET INDEX TO [<xcOrderBagName list>] [ADDITIVE]
Arguments
cOrderBagName list specifies order bags to be emptied into the order list of the current work area.
ADDITIVE adds order bags to an existing order list.
Description
By default, SET INDEX, without the ADDITIVE clause, clears the currently active order list, and then constructs a new order list from the orders in the specified order bags in the current work area. When several order bags are opened, the first order in the first order bag becomes the controlling order (has focus). The record pointer is initially positioned at the first logical identity in this order.
If an order list exists when you SET INDEX ... ADDITIVE, the orders in the new order bag are added to the end of the order list. The previous controlling order continues to be the controlling order.
If no order list exists when you SET INDEX ... ADDITIVE, the first order in the first order bag in cOrderBagName list becomes the controlling order.
During database processing, all open orders are updated whenever a key value is appended or changed, unless the order was created using a scoping condition and the key value does not match. To change the controlling order without issuing another SET INDEX command, use SET ORDER or ordSetFocus(). To add orders without closing the currently open orders, use the ADDITIVE clause.
Examples
■ This example opens a database and its associated indexes:
USE Sales NEW
SET INDEX TO Sales, Sales1, Sales2
■ This example opens an index without closing any indexes that
are already open:
SET INDEX TO Sales3 ADDITIVE
ON enables both standard and enhanced display colors.
OFF disables enhanced display color. All screen output then uses the current standard color.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
SET INTENSITY toggles the display of GETs and menu PROMPTs between enhanced and standard color settings. When INTENSITY is OFF, GETs and SAYs appear in the standard color setting. When INTENSITY is ON, GETs appear in the enhanced color setting.
When INTENSITY is OFF, all menu PROMPTs appear in the standard color setting, and the cursor appears at the current PROMPT. If INTENSITY is ON (the default), the current PROMPT appears in the enhanced color setting, and the cursor is hidden.
nInkeyCode is the Inkey() value of the key that receives the assignment.
TOidProcedure specifies the name of a procedure that executes when the user presses the assigned key. If idProcedure is not specified, the current nInkeyCode definition is released.
Description
SET KEY is a keyboard command that allows a procedure to be executed from any wait state when a designated key is pressed. A wait state is any mode that extracts keys from the keyboard except for Inkey(). These modes include AChoice(), dbEdit(), MemoEdit(), ACCEPT, INPUT, READ and WAIT. After a key is redefined, pressing it executes the specified procedure, passing three automatic parameters corresponding to ProcName(), ProcLine(), and ReadVar(). The procedure and variable parameters are character data type, while the line number is numeric data type.
You may define a maximum of 32 keys at one time. At startup, the system automatically defines the F1 key to execute Help. If a procedure with this name is linked into the current program and it is visible, pressing F1 from a wait state invokes it.
Note that SET KEY procedures should preserve the state of the application (i.e., screen appearance, current work area, etc.) and restore it before exiting.
Warning! In CA-Clipper, SET FUNCTION is preprocessed into the SET KEY and KEYBOARD commands. This means that SET FUNCTION has the effect of clearing any SET KEY for the same key number and vice versa. This is incompatible with previous releases, which maintained separate lists of SET FUNCTION keys and SET KEY keys.
Notes
■ Precedence: SET KEY definitions take precedence over SET
■ CLEAR with a SET KEY procedure: Do not use CLEAR to clear the
screen within a SET KEY procedure since it also CLEARs GETs and, therefore, terminates READ. When you need to clear the screen, use CLEAR SCREEN or CLS instead.
■ Terminating a READ from a SET KEY procedure: The following
table illustrates several ways to terminate a READ from within a SET KEY procedure.
Terminating a READ from a SET KEY Procedure
Command Action
CLEAR GETS Terminates READ without saving current GET
BREAK Terminates READ without saving current GET
KEYBOARD Ctrl-W Terminates READ and saves the current GET
KEYBOARD Esc Terminates READ without saving current GET
Examples
■ This example uses SET KEY to invoke a procedure that presents
a picklist of account identification numbers when the user presses F2
while entering data into the account identification field:
#include "Inkey.ch"
//
SET KEY K_F2 TO ScrollAccounts
USE Accounts NEW
USE Invoices NEW
@ 10, 10 GET Invoices->Id
READ
RETURN
PROCEDURE ScrollAccounts( cProc, nLine, cVar )
IF cVar = "ID"
SAVE SCREEN
Accounts->(dbEdit(10, 10, 18, 40, {"Company"}))
KEYBOARD CHR(K_CTRL_Y) + Accounts->Id + ;
Chr(K_HOME)
RESTORE SCREEN
ELSE
Tone(100, 2)
ENDIF
RETURN
TOnPageOffset is a positive number that defines the number of column positions to indent from the left side of the page for subsequent printed output. A negative value resets the MARGIN to zero.
SET MARGIN TO with no argument resets the page offset to zero, the default value.
Description
SET MARGIN is valid for all output directed to the printer from console commands and @...SAY. With console output, the nPageOffset indent is output whenever there is a new line. With @...SAY, nPageOffset is added to each column value. SET MARGIN has no effect on screen output.
Note: Printing with @...SAY and PCol() with a MARGIN SET in most cases adds the MARGIN to each column position. This happens because PCol() accurately reflects the print column position including the last nPageOffset output. The best approach is to avoid the use of SET MARGIN with PCol() for relative column addressing.
Examples
■ This example sets a page offset of 5, and then prints a list
from Sales.dbf:
USE Sales NEW
SET MARGIN TO 5
LIST Branch, Salesman TO PRINTER
SET MARGIN TO
nSize is the memo file block size. The initial memo file block size depends on the RDD. For most drivers that support the .dbt memo file format, it is 512 bytes. However, if you are using BLOB files (.dbv memo file format) via inheritance from the DBFMEMO driver, the default is 1.
Description
SET MEMOBLOCK is functionally equivalent to calling dbInfo(DBI_MEMOBLOCKSIZE, nSize). Refer to this function for more information. SET MEMOBLOCK sets the block size for the memo file associated with the database.
Examples
■ The following example illustrates the SET MEMOBLOCK command:
USE Inventor NEW
SET MEMOBLOCK TO 256
? dbInfo(DBI_MEMOBLOCKSIZE) // Result: 256
CENTER | CENTRE centers the message on the specified row.
Specifying SET MESSAGE TO 0 or SET MESSAGE TO without an argument suppresses the display of messages.
Description
SET MESSAGE is a menu command that defines the screen row where the @...PROMPT messages display. When a CA-Clipper program is invoked the default message row value is zero, suppressing all defined messages. Messages appear on nRow, column 0 unless the CENTER option is used.
Examples
■ This example creates a small lightbar menu with an activated
and centered message line:
SET MESSAGE TO 23 CENTER
SET WRAP ON
@ 5, 5 PROMPT "One" MESSAGE "Choice one"
@ 6, 5 PROMPT "Two" MESSAGE "Choice two"
MENU TO nChoice
//
IF nChoice == 0
EXIT
ELSEIF nChoice == 1
Proc1()
ELSEIF nChoice == 2
Proc2()
ENDIF
Change the setting that determines whether to optimize using the open orders when processing a filtered database file
Syntax
SET OPTIMIZE ON | OFF | (<lToggle>)
Arguments
ON enables optimization.
OFF disables optimization.
lToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Note: The initial default of this setting depends on the RDD.
Description
For RDDs that support optimization, such as DBFCDX, SET OPTIMIZE determines whether to optimize filters based on the orders open in the current work area. If this flag is ON, the RDD will optimize the search for records that meet the filter condition to the fullest extent possible, minimizing the need to read the actual data from the database file.
If this flag is OFF, the RDD will not optimize.
Examples
■ The following example enables optimization for the Inventor
database file using the SET OPTIMIZE command:
USE Inventor NEW VIA "DBFCDX"
SET OPTIMIZE ON
SET ORDER TO [<nOrder> | [TAG <cOrderName>]
[IN <xcOrderBagName>]]
Arguments
TAG is an optional clause that provides compatibility with RDDs that access multiple-order order bags. You must use this keyword anytime you specify cOrderName.
cOrderName is the name of an order, a logical arrangement of a database according to a keyed pair. This order will become the controlling order in the order list. If you specify cOrderName, you must use the keyword TAG.
Note: This differs from dBASE and FoxPro where TAG is totally optional.
nOrder is the number of the target order in the order list. You may represent the order as an integer or as a character string enclosed in quotes.
IN xcOrderBagName is the name of a disk file containing one or more orders. You may specify xcOrderBagName as the file name with or without the path name or appropriate extension. If you do not include the extension as part of xcOrderBagName, CA-Clipper uses the default extension of the current RDD.
Description
When you SET ORDER TO a new controlling order (index), all orders are properly updated when you either append or edit records. This is true even if you SET ORDER TO 0. After a change of controlling order, the record pointer still points to the same record.
SET ORDER TO 0 restores the database access to natural order, but leaves all orders open. SET ORDER TO with no arguments closes all orders and empties the order list
Though you may use cOrderName or nOrder to specify the target order, nOrder is only provided for compatibility with earlier versions of CA-Clipper. Using cOrderName is a surer way of accessing the correct order in the order list.
If you supply xcOrderBagName, only the orders belonging to xcOrderBagName in the order list are searched. Usually you need not specify xcOrderBagName if you use unique order names throughout an application.
To determine which order is the controlling order use the ordSetFocus() function.
In RDDs that support production or structural indices (e.g., DBFCDX), if you specify a tag but do not specify an order bag, the tag is created and added to the index. If no production or structural index exists, it will be created and the tag will be added to it. When using RDDs that support multiple order bags, you must explicitly SET ORDER (or ordSetFocus()) to the desired controlling order. If you do not specify a controlling order, the data file will be viewed in natural order.
SET ORDER can open orders in a network environment instead of the INDEX clause of the USE command. Generally, specify USE, and then test to determine whether the USE succeeded. If it did succeed, open the associated orders with SET ORDER. See the example below.
Examples
USE Customer NEW
IF (! NetErr())
SET ORDER TO Customer
ENDIF
SET ORDER TO "CuAcct" // CuAcct is an Order in Customer
Specify the CA-Clipper search path for opening files
Syntax
SET PATH TO [<xcPathspec list>]
Arguments
TOxcPathspec list identifies the paths CA-Clipper uses when searching for a file not found in the current directory. You can specify it as a literal list or as a character expression enclosed in parentheses. The list of paths can be separated by commas or semicolons. However, continuation of a SET PATH command line with a semicolon is not supported unless xcPathspec is specified as a character expression enclosed in parentheses.
Description
SET PATH allows commands and functions that open database and associated files to find and open existing files in another drive and/or directory. It does this by specifying a path list to search if a referenced file cannot be found in the DEFAULT or specified directory. Note that memo and low-level file functions respect neither the DEFAULT nor the path setting.
A path is a pointer to a directory. It consists of an optional drive letter and colon, followed by a list of directories from the root to the desired directory separated by backslash () characters. A path list is the sequence of paths to search, each separated by a comma or semicolon.
When you attempt to access a file, CA-Clipper first searches the default drive and directory. The default disk drive and directory are established by DOS when your CA-Clipper application is loaded or, during execution, by SET DEFAULT. If the file is not found, CA-Clipper then searches each path in the specified path list until the first occurrence of the file is found.
To create new files in another drive or directory, use SET DEFAULT TOxcPathspec or explicitly declare the path when specifying a new file name.
SET PATH TO with no argument releases the path list and CA-Clipper searches only the DEFAULT directory.
Examples
■ This example is a typical PATH command:
SET PATH TO A:\INVENTORY;B:\VENDORS
■ This example configures a path setting at runtime by passing a
DOS environment variable to a program, retrieving its value with
GetEnv(), and then setting path with this value. For example, in
DOS:
SET CLIP_PATH=C:\APPS\DATA,C:\APPS\PROGS
Later in the configuration section of your application program:
SET PATH TO (GetEnv("CLIP_PATH"))
Toggle echo of console output to the printer or set the destination of printed output
Syntax
SET PRINTER on | OFF | <xlToggle>
SET PRINTER TO [<xcDevice> | <xcFile> [ADDITIVE]]
Arguments
ON echoes console output to the printer.
OFF suppresses the printing of console output.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
TOxcDevice identifies the name of the device where all subsequent printed output will be sent. You can specify a device name as a literal character string or a character expression enclosed in parentheses. Additionally, a device can be either local or network. SETting PRINTER TO a nonexistent device creates a file with the name of the device. When specifying device names, do not use a trailing colon.
TOxcFile identifies the name of the output file. You can specify the file name as a literal string or as a character expression enclosed in parentheses. If a file extension is not specified, .prn is assumed.
ADDITIVE causes the specified output file to be appended to instead of overwritten. If ADDITIVE is not specified, an existing output file is truncated before new information is written to it. The ADDITIVE clause is only meaningful when SETting PRINTER TO an output file.
If SET PRINTER TO is specified with no arguments, the currently specified device or file is closed and the default destination is then reselected.
Description
SET PRINTER, like many other SET commands, has two basic forms with each having its own functionality. The on|OFF form of SET PRINTER controls whether the output of console commands is echoed to the printer. Console commands generally do not specify row and column coordinates. All of these commands, except ?|??, have a TO PRINTER clause that also directs output to the printer. Output from console commands is displayed to the screen unless CONSOLE is OFF. Be aware that @...SAYs are not affected by SET PRINTER ON. To send them to the printer, use SET DEVICE TO PRINTER instead.
SET PRINTER TO determines the destination of output from all commands and functions that send output to the printer. This includes @...SAYs if DEVICE is SET TO PRINTER. Output can be sent to a device or to a file. If the destination is a device, the following names are valid: LPT1, LPT2, LPT3 (all parallel ports), COM1, and COM2 (serial ports), CON and PRN. The default device is PRN.
If the destination is a file, it is created in the current DEFAULT directory. If a file with the same name exists in the same location, it is overwritten by the new file without warning. All subsequent output to the printer is then written to this file until the file is closed using SET PRINTER TO with no argument.
Use SET PRINTER TO for:
■ Managing multiple printers by swapping ports
■ Directing output to a file for printing later or for
transferring to a remote computer via telecommunications
■ Emptying the printer spooler and resetting the default device
Notes
■ Compatibility: CA-Clipper does not support the syntax SET
PRINTER TO\SPOOLER or \CAPTURE. Specifying SET PRINTER with either of these options creates the files Spooler.prn or Capture.prn. The symbols \ are ignored.
■ End of file marks: When printer output is redirected to a
file, an end of file mark (Chr(26)) is not written when the file is closed. To terminate a file with an end of file mark, issue a ?? Chr(26) just before the SET PRINTER command that closes the file.
■ Networking: For some networks, the workstation's printer
should first be redirected to the file server (usually by running the network spooler program).
Examples
■ This example echoes the output of the ? command to printer,
suppressing the console screen display by SETting CONSOLE OFF:
USE Customer NEW
SET PRINTER ON
SET CONSOLE OFF
DO WHILE !Eof()
? Customer->Name, Customer->Phone
SKIP
ENDDO
EJECT
SET PRINTER OFF
SET CONSOLE ON
CLOSE
RETURN
■ This example directs printer output to LPT1 and empties the
print spooler upon completion:
SET PRINTER TO LPT1
<Printing statements>...
SET PRINTER TO // Empty the print spooler
■ This example sends printer output to a text file, overwriting
an existing file with the same name:
SET PRINTER TO Prnfile.txt
SET DEVICE TO PRINTER
SET PRINTER ON
//
@ 0, 0 SAY "This goes to Prnfile.txt"
? "So will this!"
//
SET DEVICE TO SCREEN
SET PRINTER OFF
SET PRINTER TO // Close the print file
Compile procedures and functions into the current object (.OBJ) file
Syntax
SET PROCEDURE TO [<idProgramFile>[.<ext>]]
Arguments
TOidProgramFile is the name of the procedure file to compile into the current object file. It can optionally include a path and/or drive designator.
ext is the optional extension of the procedure. If not specified, .prg is assumed.
SET PROCEDURE TO with no argument is ignored.
Description
SET PROCEDURE directs the compiler to compile all procedures and user- defined functions declared within the specified procedure file into the current object (.OBJ) file.
SET PROCEDURE is a compatibility command and not recommended. It has been superseded by other facilities more appropriate to the compiled environment (e.g., the compiler script (.clp)) file.
See the CA-Clipper "Compiler" chapter in the Programming and Utilities Guide for a full discussion of program architecture and configuration.
Relate two work areas by a key value or record number
Syntax
SET RELATION TO [<expKey> | <nRecord> INTO <xcAlias>]
[, [TO] <expKey2> | <nRecord2> INTO <xcAlias2>...]
[ADDITIVE]
Arguments
TOexpKey is an expression that performs a SEEK in the child work area each time the record pointer moves in the parent work area. For this to work, the child work area must have an index in USE.
TOnRecord is an expression that performs a GOTO to the matching record number in the child work area each time the record pointer moves in the parent work area. If nRecord evaluates to RecNo(), the relation uses the parent record number to perform a GOTO to the same record number in the child work area. For a numeric expression type of relation to execute correctly, the child work area must not have an index in USE.
INTOxcAlias identifies the child work area and can be specified either as the literal alias name or as a character expression enclosed in parentheses.
ADDITIVE adds the specified child relations to existing relations already set in the current work area. If this clause is not specified, existing relations in the current work area are released before the new child relations are set.
SET RELATION TO with no arguments releases all relations defined in the current work area.
Description
SET RELATION is a database command that links a parent work area to one or more child work areas using a key expression, record number, or numeric expression. Each parent work area can be linked to as many as eight child work areas. A relation causes the record pointer to move in the child work area in accordance with the movement of the record pointer in the parent work area. If no match is found in the child work area, the child record pointer is positioned to LastRec() + 1, Eof() returns true (.T.), and Found() returns false (.F.).
The method of linking the parent and child work areas depends on the type of expKey and presence of an active index in the child work area. If the child work area has an active index, the lookup is a standard SEEK. If the child work area does not have an active index and the type of expKey is numeric, a GOTO is performed in the child work area instead.
Notes
■ Cyclical relations: Do not relate a parent work area to itself
either directly or indirectly.
■ Soft seeking: SET RELATION does not support SOFTSEEK and
always behaves as if SOFTSEEK is OFF even if SOFTSEEK is ON. This means that if a match is not found in the child work area, the child record pointer is always positioned to LastRec() + 1.
■ Record number relations: To relate two work areas based on
matching record numbers, use RecNo() for the SET RELATION TO expression and make sure the child work area has no active indexes.
Examples
■ This example relates three work areas in a multiple parent-
child configuration with Customer related to both Invoices and Zip:
USE Invoices INDEX Invoices NEW
USE Zip INDEX Zipcode NEW
USE Customer NEW
SET RELATION TO CustNum INTO Invoices, Zipcode INTO Zip
LIST Customer, Zip->City, Invoices->Number, ;
Invoices->Amount
■ Sometime later, you can add a new child relation using the
ADDITIVE clause, like this:
USE BackOrder INDEX BackOrder NEW
SELECT Customer
SET RELATION TO CustNum INTO BackOrder ADDITIVE
Change the top and/or bottom boundaries for scoping key values in the controlling order
Syntax
SET SCOPE TO [<expNewTop> [, <expNewBottom>]]
Arguments
expNewTop is the top range of key values that will be included in the controlling order's current scope. expNewTop can be an expression that matches the data type of the key expression in the controlling order or a code block that returns the correct data type.
expNewBottom is the bottom range of key values that will be included in the controlling order's current scope. expNewBottom can be an expression that matches the data type of the key expression in the controlling order or a code block that returns the correct data type.
Note: If expNewBottom is not specified, expNewTop is taken for both the top and bottom range values.
Description
SET SCOPE, when used with no arguments, clears the top and bottom scopes; this is equivalent to ordScope(0, NIL) followed by ordScope(1, NIL). If expNewTop is specified alone, SET SCOPE sets the top and bottom scope to the indicated value (i.e., ordScope(0, expNewTop) followed by ordScope(1, expNewTop). If both expNewTop and expNewBottom are specified, SET SCOPE sets the top and bottom scope as indicated (i.e., ordScope(0, expNewTop) followed by ordScope(1, expNewBottom). Refer to the ordScope() function for more information.
Examples
■ The following example illustrates the SET SCOPE command:
USE Inventor NEW
INDEX ON PartNo TO Parts
SET SCOPE TO 1750, 2000
// Only part numbers between 1750 and 2000 will be used
Change the bottom boundary for scoping key values in the controlling order
Syntax
SET SCOPEBOTTOM TO [<expNewBottom>]
Arguments
expNewBottom is the bottom range of key values that will be included in the controlling order's current scope. expNewBottom can be an expression that matches the data type of the key expression in the controlling order or a code block that returns the correct data type.
Description
SET SCOPEBOTTOM, when used with the expNewBottom argument, is functionally equivalent to ordScope(1, expNewBottom). SET SCOPEBOTTOM, when used with no argument, is functionally equivalent to ordScope(1, NIL). Refer to the ordScope() function for more information.
Examples
■ The following example illustrates the SET SCOPEBOTTOM command:
USE Inventor NEW
INDEX ON PartNo TO Parts
SET SCOPEBOTTOM TO 1000
// Only part numbers less than or equal to 1000
// will be used.
Change the top boundary for scoping key values in the controlling order
Syntax
SET SCOPETOP TO [<expNewTop>]
Arguments
expNewTop is the top range of key values that will be included in the controlling order's current scope. expNewTop can be an expression that matches the data type of the key expression in the controlling order or a code block that returns the correct data type.
Description
SET SCOPETOP, when used with the expNewTop argument, is functionally equivalent to ordScope(0, expNewTop). SET SCOPETOP, when used with no argument, is functionally equivalent to ordScope(0, NIL). Refer to the ordScope() function for more information.
Examples
■ The following example illustrates the SET SCOPETOP command:
USE Inventor NEW
INDEX ON PartNo TO Parts
SET SCOPETOP TO 1000
// Only part numbers greater than or equal to 1000
// will be used.
Toggle the message display from READ or MemoEdit()
Syntax
SET SCOREBOARD ON | off | <xlToggle>
Arguments
ON allows the display of messages from READ and MemoEdit() on line zero of the screen.
OFF suppresses these messages.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
SET SCOREBOARD controls whether or not messages from READ and MemoEdit() display on line zero. When SCOREBOARD is ON, READ displays messages for RANGE errors, invalid dates, and insert status. MemoEdit() displays an abort query message and the insert status.
To suppress the automatic display of these messages, SET SCOREBOARD OFF.
ON causes the record pointer to be moved to the next record with a higher key after a failed index search.
OFF causes the record pointer to be moved to Eof() after a failed index search.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
SET SOFTSEEK enables relative seeking, a method of searching an index and returning a record even if there is no match for a specified key.
When SOFTSEEK is ON and a match for a SEEK is not found, the record pointer is set to the next record in the index with a higher key value than the SEEK argument. Records are not visible because SET FILTER and/or SET DELETED are skipped when searching for the next higher key value. If there is no record with a higher key value, the record pointer is positioned at LastRec() + 1, Eof() returns true (.T.), and Found() returns false (.F.). Found() returns true (.T.) only if the record is actually found. It never returns true (.T.) for a relative find.
When SOFTSEEK is OFF and a SEEK is unsuccessful, the record pointer is positioned at LastRec() + 1, Eof() returns true (.T.), and Found() returns false (.F.).
Notes
■ SET RELATION: SET RELATION ignores SOFTSEEK updating the
record pointer in all linked child work areas as if SOFTSEEK is OFF.
Examples
■ This example illustrates the possible results of a SEEK with
SET SOFTSEEK ON:
SET SOFTSEEK ON
USE Salesman INDEX Salesman NEW
ACCEPT "Enter Salesman: " TO cSearch
SEEK cSearch
DO CASE
CASE FIELD->Salesman = cSearch
? "Match found:", Found(), Eof(), FIELD->Salesman
CASE !Eof()
? "Soft match found:", Found(), Eof(), ;
FIELD->Salesman
OTHERWISE
? "No key matches:", Found(), Eof(), FIELD->Salesman
ENDCASE
TOnKeyboardSize specifies the number of keystrokes the keyboard buffer can hold from a minimum of zero to a maximum of 4096. The default size of the keyboard buffer is machine-dependent but 16 is the minimum size.
Description
SET TYPEAHEAD defines the size of the CA-Clipper keyboard buffer that caches keystrokes input directly by the user. SET TYPEAHEAD, however, does not affect the number of characters that can be stuffed programmatically using the KEYBOARD command. When executed, SET TYPEAHEAD clears the keyboard buffer and sets the size to nKeyboardSize.
When TYPEAHEAD is SET TO zero, keyboard polling is suspended. An explicit request for keyboard input, however, will temporarily enable the keyboard and read any pending keystrokes from the BIOS buffer. Calling NextKey() constitutes such an explicit request. NextKey() reads any pending keystrokes from the BIOS buffer and returns the Inkey() value of the first keystroke read, or zero if no keystrokes are pending.
ON causes index files to be created with a uniqueness attribute.
OFF causes index files to be created without a uniqueness attribute.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
SET UNIQUE is a database command that controls whether indexes are created with uniqueness as an attribute. With UNIQUE ON, new indexes are created including only unique keys. This is the same as creating an index with the INDEX...UNIQUE command.
If, during the creation or update of an unique index, two or more records are encountered with the same key value, only the first record is included in the index. When the unique index is updated, REINDEXed, or PACKed, only unique records are maintained, without regard to the current SET UNIQUE value.
Changing key values in a unique index has important implications. First, if a unique key is changed to the value of a key already in the index, the changed record is lost from the index. Second, if there is more than one instance of a key value in a database file, changing the visible key value does not bring forward another record with the same key until the index is rebuilt with REINDEX, PACK, or INDEX...UNIQUE.
With UNIQUE OFF, indexes are created with all records in the index. Subsequent updates to the database files add all key values to the index independent of the current UNIQUE SETting.
SET UNIQUE is a compatibility command not recommended. It is superseded by the UNIQUE clause of the INDEX command.
Change the current video mode of the current application
Syntax
SET VIDEOMODE TO <nVideoMode>
Arguments
nVideoMode is a numeric value representing a particular video mode.
Description
SET VIDEOMODE changes the current display to text mode and different graphic modes. There are two modes supported by CA-Clipper: LLG_VIDEO_TEXT and LLG_VIDEO_VGA_640_480_16.
Notes
When switching from LLG_VIDEO_TEXT to LLG_VIDEO_VGA_640_480_16, all displayed text lines are converted to the equivalent graphic display. This conversion does not happen when switching back to LLG_VIDEO_TEXT mode.
If you wish to have a part of your application switch to LLG_VIDEO_VGA_640_480_16 mode and clear the screen, issue the CLS command before switching modes.
ON enables the highlight to wrap around when navigating a lightbar menu.
OFF disables wrapping when navigating a lightbar menu.
xlToggle is a logical expression that must be enclosed in parentheses. A value of true (.T.) is the same as ON, and a value of false (.F.) is the same as OFF.
Description
SET WRAP is a menu command that toggles wrapping of the highlight in an @...PROMPT menu from the first menu item to the last menu item and vice versa. When WRAP is ON and the last menu item is highlighted, Right arrow or Down arrow moves the highlight to the first menu item. Likewise, when the first menu item is highlighted, Left arrow or Up arrow moves the highlight to the last menu item.
When WRAP is OFF, pressing Up arrow or Left arrow from the first menu item or Down arrow or Right arrow from the last menu item does nothing.
nRecords is a numeric expression specifying the number of records to move the record pointer from the current position. A positive value moves the record pointer forward and a negative value moves the record pointer backward.
ALIASidAlias|nWorkArea specifies the alias name as a literal identifier or the work area as a numeric expression.
SKIP specified with no arguments moves the record pointer forward one record.
Description
SKIP moves the record pointer to a new position relative to the current position in the current work area and within the current filter, if there is one. SKIP is generally used for operations, such as reporting, that need to go to the next record in a database file.
If the alias clause is specified, the pointer can be moved in another work area without SELECTing that work area. SKIP can move either forward or backward. If there is no active index, SKIP moves the record pointer relative to the current position in the target database file. If there is an active index, SKIP moves the pointer relative to the current position in the index instead of the database file.
Attempting to SKIP forward beyond the end of file positions the record pointer at LastRec() + 1, and Eof() returns true (.T.). Attempting to SKIP backward beyond the beginning of file moves the pointer to the first record, and Bof() returns true (.T.).
In a network environment, any record movement command, including SKIP, makes changes to the current work area visible to other applications if the current file is shared and the changes were made during an RLock(). To force an update to become visible without changing the current record position, use SKIP 0. If, however, the changes were made during an FLock(), visibility is not guaranteed until the lock is released, a COMMIT is performed, or the file is closed. Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information.
Examples
■ This example uses SKIP with various arguments and shows their
results:
USE Customers NEW
SKIP
? RecNo() // Result: 2
SKIP 10
? RecNo() // Result: 12
SKIP -5
? RecNo() // Result: 7
■ This example moves the record pointer in a remote work area:
USE Customers NEW
USE Invoices NEW
SKIP ALIAS Customers
■ This example prints a report using SKIP to move the record
pointer sequentially through the Customer database file:
LOCAL nLine := 99
USE Customers NEW
SET PRINTER ON
DO WHILE !Eof()
IF nLine > 55
EJECT
nLine := 1
ENDIF
? Customer, Address, City, State, Zip
nLine++
SKIP
ENDDO
SET PRINTER OFF
CLOSE Customers
SoundEx() returns a four-digit character string in the form A999.
Description
SoundEx() is a character function that indexes and searches for sound- alike or phonetic matches. It is used in applications where the precise spelling of character keys is not known or where there is a high probability of misspelled names. Misspelling is common in real-time transaction systems where the data entry operator is receiving information over the telephone. SoundEx() works by bringing sound-alikes together under the same key value. Note, however, the soundex method is not absolute. Keys that are quite different can result in the same soundex value.
Examples
■ This example builds an index using SoundEx() to create the key
values. It then searches for a value found in the Salesman field:
USE Sales
INDEX ON SoundEx(Salesman) TO Salesman
SEEK SoundEx("Smith")
? Found(), Salesman // Result: .T. Smith
■ Here, a search is made for the same key as above but with a
different spelling:
SEEK SoundEx("Smythe")
? Found(), Salesman // Result: .T. Smith
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/SOUNDEX.C.
SORT TO <xcDatabase> ON <idField1> [/[A | D][C]]
[, <idField2> [/[A | D][C]]...]
[<scope>] [WHILE <lCondition>] [FOR <lCondition>]
Arguments
TOxcDatabase is the name of the target file for the sorted records and can be specified either as a literal file name or as a character expression enclosed in parentheses. Unless otherwise specified, the new file is assigned a (.dbf) extension.
ONidField is the sort key and must be a field variable.
/[A|D][C] specifies how xcDatabase is to be sorted. /A sorts in ascending order. /D sorts in descending order. /C sorts in dictionary order by ignoring the case of the specified character field. The default SORT order is ascending.
scope is the portion of the current database file to SORT. The default is ALL records.
WHILElCondition specifies the set of records meeting the condition from the current record until the condition fails.
FORlCondition specifies the conditional set of records to SORT within the given scope.
Description
SORT is a database command that copies records from the current work area to another database file in sorted order. CA-Clipper SORTs character fields in accordance with the ASCII value of each character within the string unless the /C option is specified. This option causes the database file to be sorted in dictionary order—capitalization is ignored. Numeric fields are sorted in numeric order, date fields are sorted chronologically, and logical fields are sorted with true (.T.) as the high value. Memo fields cannot be sorted.
SORT performs as much of its operation as possible in memory, and then, it spools to a uniquely named temporary disk file. This temporary file can be as large as the size of the source database file. Note also that a SORT uses up three file handles: the source database file, the target database file, and the temporary file.
In a network environment, you must lock the database file to be SORTed with FLock() or USE it EXCLUSIVEly.
Notes
■ Deleted source records: If DELETED is OFF, SORT copies deleted
records to the target database file; however, the deleted records do not retain their deleted status. No record is marked for deletion in the target file regardless of its status in the source file.
If DELETED is ON, deleted records are not copied to the target database file. Similarly, filtered records are ignored during a SORT and are not included in the target file.
Examples
■ This example copies a sorted subset of a mailing list to a
smaller list for printing:
USE Mailing INDEX Zip
SEEK "900"
SORT ON LastName, FirstName TO Invite WHILE Zip = "900"
USE Invite NEW
REPORT FORM RsvpList TO PRINTER
nCount is the number of spaces to be returned, up to a maximum of 65,535 (64 K).
Returns
Space() returns a character string. If nCount is zero, Space() returns a null string ("").
Description
Space() is a character function that returns a specified number of spaces. It is the same as Replicate("", nCount). Space() can initialize a character variable before associating it with a GET. Space() can also pad strings with leading or trailing spaces. Note, however, that the PadC(), PadL(), and PadR() functions are more effective for this purpose.
Examples
■ This example uses Space() to initialize a variable for data
input:
USE Customer NEW
MEMVAR->Name = Space(Len(Customer->Name))
@ 10,10 SAY "Customer Name" GET MEMVAR->Name
READ
nNumber is a positive number for which the square root is to be computed.
Returns
Sqrt() returns a numeric value calculated to double precision. The number of decimal places displayed is determined solely by SET DECIMALS regardless of SET FIXED. A negative nNumber returns zero.
Description
Sqrt() is a numeric function used anywhere in a numeric calculation to compute a square root (e.g., in an expression that calculates standard deviation).
Examples
■ These examples show various results of Sqrt():
SET DECIMALS TO 5
//
? Sqrt(2) // Result: 1.41421
? Sqrt(4) // Result: 2.00000
? Sqrt(4) ** 2 // Result: 4.00000
? Sqrt(2) ** 2 // Result: 2.00000
nNumber is the numeric expression to be converted to a character string.
nLength is the length of the character string to return, including decimal digits, decimal point, and sign.
nDecimals is the number of decimal places to return.
Returns
Str() returns nNumber formatted as a character string. If the optional length and decimal arguments are not specified, Str() returns the character string according to the following rules:
Results of Str() with No Optional Arguments
Expression Return Value Length
Field Variable Field length plus decimals
Expressions/constants Minimum of 10 digits plus decimals
Val() Minimum of 3 digits
Month()/Day() 3 digits
Year() 5 digits
RecNo() 7 digits
Description
Str() is a numeric conversion function that converts numeric values to character strings. It is commonly used to concatenate numeric values to character strings. Str() has applications displaying numbers, creating codes such as part numbers from numeric values, and creating index keys that combine numeric and character data.
Str() is like Transform(), which formats numeric values as character strings using a mask instead of length and decimal specifications.
The inverse of Str() is Val(), which converts character numbers to numerics.
Notes
■ If nLength is less than the number of whole number digits in
nNumber, Str() returns asterisks instead of the number.
■ If nLength is less than the number of decimal digits
required for the decimal portion of the returned string, CA-Clipper rounds the number to the available number of decimal places.
■ If nLength is specified but nDecimals is omitted (no
decimal places), the return value is rounded to an integer.
Examples
■ These examples demonstrate the range of values returned by
Str(), depending on the arguments specified:
nNumber:= 123.45
? Str(nNumber) // Result: 123.45
? Str(nNumber, 4) // Result: 123
? Str(nNumber, 2) // Result: **
? Str(nNumber * 10, 7, 2) // Result: 1234.50
? Str(nNumber * 10, 12, 4) // Result: 1234.5000
? Str(nNumber, 10, 1) // Result: 1234.5
■ This example uses Str() to create an index with a compound key
of order numbers and customer names:
USE Customer NEW
INDEX ON Str(NumOrders, 9) + CustName TO CustOrd
cString is the character string or memo field to be searched.
cSearch is the sequence of characters to be located.
cReplace is the sequence of characters with which to replace cSearch. If this argument is not specified, the specified instances of the search argument are replaced with a null string ("").
nStart is the first occurrence that will be replaced. If this argument is omitted, the default is one. If this argument is equal to or less than zero, StrTran() returns an empty string.
nCount is the number of occurrences to be replaced. If this argument is not specified, the default is all.
Returns
StrTran() returns a new character string with the specified instances of cSearch replaced with cReplace.
Description
StrTran() is a character function that performs a standard substring search within a character string. When it finds a match, it replaces the search string with the specified replacement string. All instances of cSearch are replaced unless nStart or nCount is specified. Note that StrTran() replaces substrings and, therefore, does not account for whole words.
Examples
■ This example uses StrTran() to establish a postmodern analog
to a famous quotation:
cString:= "To compute, or not to compute?"
? StrTran(cString, "compute", "be")
// Result: To be, or not to be?
cString is the target character string into which characters are inserted and deleted.
nStart is the starting position in the target string where the insertion/deletion occurs.
nDelete is the number of characters to be deleted.
cInsert is the string to be inserted.
Returns
Stuff() returns a copy of cString with the specified characters deleted and with cInsert inserted.
Description
Stuff() is a character function that deletes nDelete characters from cString beginning at the nStart position. Then, it inserts cInsert into the resulting string beginning at nStart to form the return string. With this, Stuff() can perform the following six operations:
■ Insert: If nDelete is zero, no characters are removed from
cString. cInsert is then inserted at nStart, and the entire string is returned. For example, Stuff("My dog has fleas.", 12, 0, "no" ) returns "My dog has no fleas."
■ Replace: If cInsert is the same length as nDelete,
cInsert replaces characters beginning at nStart. The same number of characters are deleted as are inserted, and the resulting string is the same length as the original. For example, Stuff("My dog has fleas.", 12, 5, "bones") returns "My dog has bones."
■ Delete: If cInsert is a null string (""), the number of
characters specified by nDelete are removed from cString, and the string is returned without any added characters. For example, Stuff("My dog has fleas.", 1, 3, "") returns "dog has fleas."
■ Replace and insert: If cInsert is longer than nDelete, all
characters from nStart up to nDelete are replaced and the rest of cInsert is inserted. Since more characters are inserted than are deleted, the resulting string is always longer than the original. For example, Stuff("My dog has fleas.", 8, 3, "does not have") returns "My dog does not have fleas."
■ Replace and delete: If the length of cInsert is less than
nDelete, more characters are deleted than inserted. The resulting string, therefore, is shorter than the original. For example, Stuff("My dog has fleas.", 8, 3, "is") returns "My dog is fleas."
■ Replace and delete rest: If nDelete is greater than or equal
to the number of characters remaining in cString beginning with nStart, all remaining characters are deleted before cInsert is inserted. For example, Stuff("My dog has fleas.", 8, 10, "is.") returns "My dog is."
Declare and initialize static variables and arrays
Syntax
STATIC <identifier> [[:= <initializer>], ... ]
Arguments
identifier is the name of the variable or array to declare static. If the identifier is followed by square brackets ([ ]), it is created as an array. If the identifier is an array, the syntax for specifying the number of elements for each dimension can be array[nElements, nElements2,...] or array[nElements] [nElements2]... The maximum number of elements is 4096. The maximum number of dimensions is limited only by available memory.
initializer is the optional assignment of a value to a new static variable. An initializer for a static variable consists of the inline assignment operator (:=) followed by a compile-time constant expression consisting entirely of constants and operators or a literal array. If no explicit initializer is specified, the variable is given an initial value of NIL. In the case of an array, each element is NIL. Array identifiers cannot be given values with an initializer.
Note: The macro operator (&) cannot be used in a STATIC declaration statement.
Description
The STATIC statement declares variables and arrays that have a lifetime of the entire program but are only visible within the entity that creates them. Static variables are visible only within a procedure or user-defined function if declared after a PROCEDURE or FUNCTION statement. Static variables are visible to all procedures and functions in a program (.prg) file (i.e., have filewide scope) if they are declared before the first procedure or user-defined function definition in the file. Use the /N compiler option to compile a program with filewide variable scoping.
All static variables in a program are created when the program is first invoked, and all values specified in a static initializer are assigned to the variable before the beginning of program execution.
Declarations of static variables within a procedure or user-defined function must occur before any executable statement including PRIVATE, PUBLIC, and PARAMETERS. If a variable of the same name is declared FIELD, LOCAL, or MEMVAR within the body of a procedure or user-defined function, a compiler error occurs and no object (.OBJ) file is generated.
The maximum number of static variables in a program is limited only by available memory.
Notes
■ Inspecting static variables within the Debugger: To access
static variable names within the CA-Clipper debugger, you must compile program (.prg) files using the /B option so that static variable information is included in the object (.OBJ) file.
■ Macro expressions: You may not refer to static variables
within macro expressions or variables. If a static variable is referred to within a macro expression or variable, a private or public variable of the same name will be accessed instead. If no such variable exists, a runtime error will be generated.
■ Memory files: Static variables cannot be SAVED to or RESTOREd
from memory (.mem) files.
■ Type of a static local variable: Since Type() uses the macro
operator (&) to evaluate its argument, you cannot use Type() to determine the type of a local or static variable or an expression containing a local or static variable reference. The ValType() function provides this facility by evaluating the function argument and returning the data type of its return value.
Examples
■ This example declares static variables both with and without
initializers:
STATIC aArray1[20, 10], aArray2[20][10]
STATIC cVar, cVar2
STATIC cString := "my string", var
STATIC aArray := {1, 2, 3}
■ This example manipulates a static variable within a user-
defined function. In this example, a count variable increments
itself each time the function is called:
FUNCTION MyCounter( nNewValue )
STATIC nCounter := 0 // Initial value assigned once
IF nNewValue != NIL
nCounter:= nNewValue // New value for nCounter
ELSE
nCounter++ // Increment nCounter
ENDIF
RETURN nCounter
■ This example demonstrates a static variable declaration that
has filewide scope. In this code fragment, aArray is visible to both
procedures that follow the declaration:
STATIC aArray := {1, 2, 3, 4}
FUNCTION One
? aArray[1] // Result: 1
RETURN NIL
FUNCTION Two
? aArray[3] // Result: 3
RETURN NIL
STORE <exp> TO <idVar list>
<idVar> = <exp>
<idVar> := [ <idVar2> := ...] <exp>
Arguments
exp is a value of any data type that is assigned to the specified variables.
TOidVar list defines a list of one or more local, static, public, private, or field variables that are assigned the value exp. If any idVar is not visible or does not exist, a private variable is created and assigned exp.
Description
STORE assigns a value to one or more variables of any storage class. The storage classes of CA-Clipper variables are local, static, field, private, and public. STORE is identical to the simple assignment operators (=) and (:=). In fact, a STORE statement is preprocessed into an assignment statement using the inline operator (:=). Like all of the assignment operators, STORE assigns to the most recently declared and visible variable referenced by idVar. If, however, the variable reference is ambiguous (i.e., not declared at compile time or not explicitly qualified with an alias), it is assumed to be MEMVAR. At runtime, if no private or public variable exists with the specified name, a private variable is created.
To override a declaration, you can specify the idVar prefaced by an alias. If idVar is a field variable, use the name of the work area. For private and public variables, you can use the memory variable alias (MEMVAR->). To assign to a field variable in the currently selected work area (as opposed to a particular named work area), you can use the field alias (FIELD->).
As a matter of principle, all variables other than field variables should be declared. Preface field variables with the alias. Use of private and public variables is discouraged since they violate basic principles of modular programming and are much slower than local and static variables.
Note that the STORE command is a compatibility command and not recommended for any assignment operation. CA-Clipper provides assignment operators that supersede the STORE command, including the inline assignment operator (:=), the increment and decrement operators (++) and (—), and the compound assignment operators (+=, -=, *=, /=). Refer to the Operators and Variables sections of the "Basic Concepts" chapter in the Programming and Utilities Guide for more information.
Notes
■ Assigning a value to an entire array: In CA-Clipper, neither
the STORE command nor the assignment operators can assign a single value to an entire array. Use the AFill() function for this purpose.
■ Memo fields: Assigning a memo field to a variable assigns a
character value to that variable.
Examples
■ These statements create and assign values to undeclared
private variables:
STORE "string" TO cVar1, cVar2, cVar3
cVar1:= "string2"
cVar2:= MEMVAR->cVar1
■ These statements assign multiple variables using both STORE
and the inline assignment operator (:=). The methods produce
identical code:
STORE "value" to cVar1, cVar2, cVar3
cVar1 := cVar2 := cVar3 := "value"
■ These statements assign values to the same field referenced
explicitly with an alias. The first assignment uses the field alias
(FIELD->), where the second uses the actual alias name:
USE Sales NEW
FIELD->CustBal = 1200.98
Sales->CustBal = 1200.98
cString is the character string from which to extract a substring. It can be up to 65,535 (64K) bytes, the maximum character string size in CA-Clipper.
nStart is the starting position in cString. If nStart is positive, it is relative to the leftmost character in cString. If nStart is negative, it is relative to the rightmost character in the cString.
nCount is the number of characters to be extracted. If omitted, the substring begins at nStart and continues to the end of the string. If nCount is greater than the number of characters from nStart to the end of cString, the excess numbers are ignored.
Returns
SubStr() returns a character string.
Description
SubStr() is a character function that extracts a substring from another character string or memo field. SubStr() is related to the Left() and Right() functions which extract substrings beginning with leftmost and rightmost characters in cString, respectively.
The SubStr(), Right(), and Left() functions are often used with both the At() and RAt() functions to locate either the first and/or the last position of a substring before extracting it. They are also used to display or print only a portion of a character string.
Examples
■ These examples extract the first and last name from a
variable:
cName:= "Biff Styvesent"
? SubStr(cName, 1, 4) // Result: Biff
? SubStr(cName, 6) // Result: Styvesent
? SubStr(cName, Len(cName) + 2) // Result: null string
? SubStr(cName, -9) // Result: Styvesent
? SubStr(cName, -9, 3) // Result: Sty
■ This example uses SubStr() with At() and RAt() to create a
user-defined function to extract a file name from a file
specification:
? FileBase("C:\PRG\MYFILE.OBJ") // Result: MYFILE.OBJ
FUNCTION FileBase( cFile )
LOCAL nPos
IF (nPos := RAt("\", cFile)) != 0
RETURN SubStr(cFile, nPos + 1)
ELSEIF (nPos := At(":", cFile)) != 0
RETURN SubStr(cFile, nPos + 1)
ELSE
RETURN cFile
ENDIF
Sum numeric expressions and assign results to variables
Syntax
SUM <nExp list> TO <idVar list>
[<scope>] [WHILE <lCondition>] [FOR <lCondition>]
Arguments
nExp list is the list of numeric values to sum for each record processed.
TOidVar list identifies the receiving variables to be assigned assign the results of the sum. Variables that either do not exist or are not visible are created as private variables. idVar list must contain the same number of elements as nExp list.
scope is the portion of the current database file to SUM. The default scope is ALL records.
WHILElCondition specifies the set of records meeting the condition from the current record until the condition fails.
FORlCondition specifies the conditional set of records to SUM within the given scope.
Description
SUM is a database command that totals a series of numeric expressions for a range of records in the current work area and assigns the results to a series of variables. The variables specified in idVar list can be field, local, private, public, or static.
Note that the nExp list is required and not optional as it is in other dialects.
Examples
■ This example illustrates the use of SUM:
LOCAL nTotalPrice, nTotalAmount
USE Sales NEW
SUM Price * .10, Amount TO nTotalPrice, nTotalAmount
//
? nTotalPrice // Result: 151515.00
? nTotalAmount // Result: 150675.00
A TBColumn object is a simple object containing the information needed to fully define one data column of a TBrowse object.
Methods link
Class Function
TBColumnNew() Create a new TBColumn object
TBColumnNew(cHeading, bBlock) → oTBColumn
Returns
Returns a new TBColumn object with the specified heading and data retrieval block. Other elements of the TBColumn object can be assigned directly using the syntax for assigning exported instance variables.
Exported Instance Variables
block Code block to retrieve data for the column
block (Assignable)
Contains a code block that retrieves data for the column. Any code block is valid, and no block arguments are supplied when the block is evaluated. The code block must return the appropriate data value for the column.
cargo User-definable variable
cargo (Assignable)
Contains a value of any data type provided as a user-definable slot, allowing arbitrary information to be attached to a TBColumn and retrieved later.
colorBlock Code block that determines color of data items
colorBlock (Assignable)
Contains an optional code block that determines the color of data items as they are displayed. If present, this block is executed each time a new value is retrieved via the TBColumn:block (the data retrieval block). The newly retrieved data value is passed as an argument to the TBColumn:colorBlock, which must return an array containing four numeric values. The values returned are used as indexes into the color table of the TBrowse object as described in the TBColumn:defColor reference below.
The TBColumn:colorBlock allows display colors for data items based on the value of the data being displayed. For example, negative numbers may be displayed in a different color than positive numbers.
Note: The colors available to a DOS application are more limited than those for a Windows application. The only colors available to you here are listed in the drop-down list box of the Properties Workbench window for that item.
colSep Column separator character
colSep (Assignable)
Contains an optional character string that draws a vertical separator to the left of this column if there is another column to the left of it. If no value is supplied for TBColumn:colSep, the value contained in TBrowse:colSep is used instead.
defColor Array of numeric indexes into the color table
defColor (Assignable)
Contains an array of four numeric values used as indexes into the color table in the TBrowse object. The first value determines the unselected color which displays data values when the browse cursor is not on the data value being displayed. The second value determines the selected color. The selected color displays the current browse cell. The third color displays the heading. The fourth color displays the footing.
The default value for TBColumn:defColor is {1, 2, 1, 1}. This causes the first two colors in the TBrowse color table to be used for unselected and selected, respectively. Note that colors set using TBColumn:colorBlock override those set by TBColumn:defColor.
footing Column footing
footing (Assignable)
Contains a character value that defines the footing for this data column.
footSep Footing separator character
footSep (Assignable)
Contains a character value that draws a horizontal line between the data values and the footing. If it does not contain a character value, TBrowse:footSep is used instead.
heading Column heading
heading (Assignable)
Contains a character value that defines the heading for this data column.
headSep Heading separator character
headSep (Assignable)
Contains an optional character string that draws a horizontal separator between the heading and the data values. If it does not contain a character value, the TBrowse:headSep is used instead.
picture Character string controlling column formatting and editing
picture (Assignable)
Contains an optional character string that controls formatting and editing of the column. See the @...GET entry in the Reference Guide, Volume 1 for more information on PICTURE strings.
postBlock Code block validating values
postBlock (Assignable)
Contains an optional code block that validates a newly entered or modified value contained within a given cell.. If present, the TBColumn:postBlock should contain an expression that evaluates to true (.T.) for a legal value and false (.F.) for an illegal value.
The TBColumn object itself ignores this variable. It is typically used by the standard READ command.
During postvalidation, the TBColumn:postBlock is passed a reference to the current Get object as an argument.
preBlock Code block determining editing
preBlock (Assignable)
Contains an optional code block that decides whether editing should be permitted. If present, the TBColumn:preBlock should evaluate to true (.T.) if the cursor enters the editing buffer; otherwise, it should evaluate to false (.F.).
The TBColumn object itself ignores this variable. It is typically used by the standard READ command.
During prevalidation, the TBColumn:preBlock is passed a reference to the current Get object as an argument.
width Column display width
width (Assignable)
Contains a numeric value that defines the display width for the column. If TBColumn:width is not explicitly set, the width of the column will be the greater of the length of the heading, the length of the footing, or the length of the data at the first evaluation of TBColumn:block.
If this instance variable is explicitly set, the width of the column will be TBColumn:width. Displayed headings, footings, and data will all be truncated to this width when necessary. The width of the displayed data will be the length at the first evaluation of TBColumn:block for all data types other than character. Character data will be extended to TBColumn:width for display purposes.
Exported Methods
setstyle() Maintains dictionary within object
setstyle(nStyle, [lSetting]) → self
TBColumn:setStyle() maintains a dictionary within a TBColumn object. This dictionary, which is simply an array, contains a set of logical values that determine behaviors associated with a TBrowse column. nStyle refers to the element in the dictionary that contains the style. lSetting indicates whether the style should be permitted or denied. Set to true (.T.) to allow the behavior to occur; otherwise, set to false (.F.) to prohibit it. CA-Clipper reserves the first three elements of the dictionary for predefined styles.
You may add custom styles to a TBColumn object by specifying any unused element of the dictionary. A maximum of 4096 definitions is available. When adding new styles to the dictionary, use the TBC_CUSTOM constant to ensure that the new styles will not interfere with the predefined ones. This guarantees that if more predefined styles are added in future releases of CA-Clipper, the positions of your styles in the dictionary will be adjusted automatically.
Styles are used by neither the TBColumn object nor the TBrowse object. The style dictionary is merely a convenient method of associating behaviors with a TBColumn object. The functions that query and implement these behaviors are external to the object. An example of this can be found in BrowSys.prg in the clip53\samples subdirectory.
TBColumn Styles
Number TBrowse.ch Meaning
1 TBC_READWRITE Can the user modify the data in the column's
cells?
2 TBC_MOVE Can the user move the column to another
position in the browse?
3 TBC_SIZE Can the user modify the width of the column?
4 TBC_CUSTOM First available element for custom styles.
Tbrowse.ch contains manifest constants for TBColumn:SetStyle().
Note: TBC_MOVE and TBC_SIZE are not implemented in CA-Clipper 5.3. They are reserved for future usage.
Examples
■ This example is a code fragment that creates a TBrowse object
and adds some TBColumn objects to it:
USE Customer NEW
//
// Create a new TBrowse object
objBrowse := TBrowseDB(1, 1, 23, 79)
//
// Create some new TBColumn objects and
// add them to the TBrowse object
objBrowse:addColumn(TBColumnNew("Customer", ;
{|| Customer->Name}))
objBrowse:addColumn(TBColumnNew("Address", ;
{|| Customer->Address}))
objBrowse:addColumn(TBColumnNew("City", ;
{|| Customer->City}))
.
. <statements to actually browse the data>
.
CLOSE Customer
For more information on TBrowse, refer to the "Introduction to
TBrowse" chapter in the Programming and Utilities Guide. For a fully
operational example of a TBrowse object, see TbDemo.prg located in
\CLIP53\SOURCE\SAMPLE.
A TBrowse object is a general purpose browsing mechanism for table-oriented data. TBrowse objects provide a sophisticated architecture for acquiring, formatting, and displaying data. Data retrieval and file positioning are performed via user-supplied code blocks, allowing a high degree of flexibility and interaction between the browsing mechanism and the underlying data source. The format of individual data items can be precisely controlled via the TBColumn data retrieval code blocks; overall display formatting and attributes can be controlled by sending appropriate messages to the TBrowse object.
Note: TBrowse has a memory limit of 200 fields.
A TBrowse object relies on one or more TBColumn objects. A TBColumn object contains the information necessary to define a single column of the browse table (see TBColumn class in this chapter).
During operation, a TBrowse object retrieves data by evaluating code blocks. The data is organized into rows and columns and displayed within a specified rectangular region of the screen. The TBrowse object maintains an internal browse cursor. The data item on which the browse cursor rests is displayed in a highlighted color. (The actual screen cursor is also positioned to the first character of this data item.)
Initially, the browse cursor is placed on the data item at the top left of the browse display. Messages can then be sent to the TBrowse object to navigate the displayed data, causing the browse cursor to move. These messages are normally sent in response to user keystrokes.
New data is automatically retrieved as required by navigation requests. When navigation proceeds past the edge of the visible rectangle, rows or columns beyond that edge are automatically brought into view. When new rows are brought into view, the underlying data source is repositioned by evaluating a code block.
Note: TBrowse objects do not clear the entire window before output during redisplay operations. Part of the window may still be cleared when data from the existing display is scrolled.
Methods link
Class Functions
TBrowseDB() Create a new TBrowse object for browsing a database file
TBrowseDB(nTop, nLeft, nBottom, nRight)
→ oTBrowse
Returns
TBrowseDB() returns a new TBrowse object with the specified coordinate settings and default code blocks for data source positioning within database files. The coordinate settings are defined by nTop, nLeft, nBottom, and nRight. The default code blocks execute the GO TOP, GO BOTTOM, and SKIP operations. Note that TBrowseDB() creates an object with no column objects. To make the TBrowse object usable, you must add a column for each field to be displayed.
TBrowseNew() returns a new TBrowse object with the specified coordinate settings defined by nTop, nLeft, nBottom, and nRight. The TBrowse object is created with no columns and no code blocks for data positioning. These must be provided before the TBrowse object can be used.
Exported Instance Variables
autoLite Logical value to control highlighting
autoLite (Assignable)
Contains a logical value. When autoLite is set to true (.T.), the stabilize method automatically highlights the current cell as part of stabilization. The default for autoLite is true (.T.).
border Character value defining characters drawn around object
border (Assignable)
Contains a character value that defines the characters that comprise the box that is drawn around the TBrowse object on the screen. Its length must be either zero or eight characters. If not specified, the browse appears without a border. When present, the browse occupies the region of the screen specified by TBrowse:nTop + 1, TBrowse:nLeft + 1, TBrowse:nBottom - 1, TBrowse:nRight - 1. This effectively decreases the number of screen rows and columns that the browse occupies by two.
cargo User-definable variable
cargo (Assignable)
Contains a value of any data type provided as a user-definable slot. TBrowse:cargo allows arbitrary information to be attached to a TBrowse object and retrieved later.
colCount Number of browse columns
colCount
Contains a numeric value indicating the total number of data columns in the browse. For each column, there is an associated TBColumn object.
colorSpec Color table for the TBrowse display
colorSpec (Assignable)
Contains a character string defining a color table for the TBrowse display. As a default, the current SetColor() value is copied into this variable when the TBrowse object is created.
Note: The colors available to a DOS application are more limited than those for a Windows application. The only colors available to you here are listed in the drop-down list box of the Properties Workbench window for that item.
colPos Current cursor column position
colPos (Assignable)
Contains a numeric value indicating the data column where the browse cursor is currently located. Columns are numbered from 1, starting with the leftmost column.
colSep Column separator character
colSep (Assignable)
Contains a character value that defines a column separator for TBColumns that do not contain a column separator of their own (see TBColumn class in this chapter for more information).
footSep Footing separator character
footSep (Assignable)
Contains a character value that defines a footing separator for TBColumn objects not containing a footing separator of their own (see TBColumn class in this chapter).
freeze Number of columns to freeze
freeze (Assignable)
Contains a numeric value that defines the number of data columns frozen on the left side of the display. Frozen columns are always visible, even when other columns are panned off the display.
goBottomBlock Code block executed by TBrowse:goBottom()
goBottomBlock (Assignable)
Contains a code block executed in response to the TBrowse:goBottom() message. This block is responsible for repositioning the data source to the last record displayable in the browse. Typically the data source is a database file, and this block contains a call to a user- defined function that executes a GO BOTTOM command.
goTopBlock Code block executed by TBrowse:goTop()
goTopBlock (Assignable)
Contains a code block that is executed in response to the TBrowse:goTop() message. This block is responsible for repositioning the data source to the first record displayable in the browse. Typically the data source is a database file, and this block contains a call to a user-defined function that executes a GO TOP command.
headSep Heading separator character
headSep (Assignable)
Contains a character value that defines a heading separator for TBColumn objects not containing a heading separator of their own (see TBColumn class in this chapter).
hitBottom Indicates the end of available data
hitBottom (Assignable)
Contains a logical value indicating whether an attempt was made to navigate beyond the end of the available data. TBrowse:hitBottom contains true (.T.) if an attempt was made; otherwise it contains false (.F.). During stabilization, the TBrowse object sets this variable if TBrowse:skipBlock indicates it was unable to skip forward as many records as requested.
hitTop Indicates the beginning of available data
hitTop (Assignable)
Contains a logical value indicating whether an attempt was made to navigate past the beginning of the available data. TBrowse:hitTop contains true (.T.) if an attempt was made; otherwise it contains false (.F.). During stabilization, the TBrowse object sets this variable if TBrowse:skipBlock indicates that it was unable to skip backward as many records as requested.
leftVisible Indicates position of leftmost unfrozen column in display
leftVisible
Contains a numeric value indicating the position of the leftmost unfrozen column visible in the browse display. If every column is frozen in the display, TBrowse:leftVisible contains zero.
mColPos Numeric value indicating mouse position
mColPos (Assignable)
Contains a numeric value indicating the data column where the mouse cursor is currently located. Columns are numbered from 1, starting with the leftmost column.
message Character string displayed on status bar
message (Assignable)
Contains a character string that is displayed on the GET system's status bar line when the TBrowse is utilized within the GET system. Typically, it describes the anticipated contents of, or user response to, the browse. Refer to @ ...GETTBROWSE and the READ command for details pertaining to the GET system's status bar.
mRowPos Numeric value indicating the data row of the mouse position
mRowPos (Assignable)
Contains a numeric value indicating the data row where the mouse cursor is currently located. Data rows are numbered from 1, starting with the topmost data row. Screen rows containing headings, footings, or separators are not considered data rows.
nBottom Bottom row number for the TBrowse display
nBottom (Assignable)
Contains a numeric value defining the bottom screen row used for the TBrowse display.
nLeft Leftmost column for the TBrowse display
nLeft (Assignable)
Contains a numeric value defining the leftmost screen column used for the TBrowse display.
nRight Rightmost column for the TBrowse display
nRight (Assignable)
Contains a numeric value defining the rightmost screen column used for the TBrowse display.
nTop Top row number for the TBrowse display
nTop (Assignable)
Contains a numeric value defining the top screen row used for the TBrowse display.
rightVisible Indicates position of rightmost unfrozen column in display
rightVisible
Contains a numeric value indicating the position of the rightmost unfrozen column visible in the browse display. If all columns visible in the display are frozen, TBrowse:rightVisible contains zero.
rowCount Number of visible data rows in the TBrowse display
rowCount
Contains a numeric value indicating the number of data rows visible in the browse display. Only data rows are included in the count. Rows occupied by headings, footings, or separators are not included.
rowPos Current cursor row position
rowPos (Assignable)
Contains a numeric value indicating the data row where the browse cursor is currently located. Data rows are numbered from 1, starting with the topmost data row. Screen rows containing headings, footings, or separators are not considered data rows.
skipBlock Code block used to reposition data source
skipBlock (Assignable)
Contains a code block that repositions the data source. During stabilization, this code block is executed with a numeric argument when the TBrowse object needs to reposition the data source. The numeric argument passed to the block represents the number of records to be skipped. A positive value means skip forward, and a negative value means skip backward. A value of zero indicates that the data source does not need to be repositioned, but the current record may need to be refreshed. Typically, the data source is a database file, and this block calls a user-defined function that executes a SKIP command to reposition the record pointer.
The block must return the number of rows (positive, negative, or zero) actually skipped. If the value returned is not the same as the value requested, the TBrowse object assumes that the skip operation encountered the beginning or end of file.
stable Indicates if the TBrowse object is stable
stable (Assignable)
Contains a logical value indicating whether the TBrowse object is stable. It contains true (.T.) if the TBrowse object is stable; otherwise, it contains false (.F.). The browse is considered stable when all data has been retrieved and displayed, the data source has been repositioned to the record corresponding to the browse cursor, and the current cell has been highlighted. When navigation messages are sent to the TBrowse object, TBrowse:stable is set to false (.F.). After stabilization is performed using the TBrowse:stabilize() message, TBrowse:stable is set to true (.T.).
Exported Methods
Cursor Movement Methods
down() Moves the cursor down one row
down() → self
Moves the browse cursor down one row. If the cursor is already on the bottom row, the display is scrolled up and a new row is brought into view. If the data source is already at the logical end of file and the browse cursor is already on the bottom row, TBrowse:hitBottom is set true (.T.).
end() Moves the cursor to the rightmost visible data column
end() → self
Moves the browse cursor to the rightmost data column currently visible.
goBottom() Repositions the data source to the bottom of file
goBottom() → self
Repositions the data source to logical bottom of file (by evaluating the TBrowse:goBottomBlock), refills the display with the bottommost available data, and moves the browse cursor to the lowermost data row for which data is available. The pan position of the window is not changed.
goTop() Repositions the data source to the top of file
goTop() → self
Repositions the data source to the logical beginning of file (by evaluating the TBrowse:goTopBlock), refills the display with the topmost available data, and moves the browse cursor to the uppermost data row for which data is available. The pan position of the window is not changed.
home() Moves the cursor to the leftmost visible data column
home() → self
Moves the browse cursor to the leftmost unfrozen column on the display.
Moves the browse cursor left one data column. If the cursor is already on the leftmost displayed column, the display is panned and the previous data column (if there is one) is brought into view.
pageDown() Repositions the data source downward
pageDown() → self
Repositions the data source downward and refills the display. If the data source is already at the logical end of file (i.e., the bottommost available record is already shown), the browse cursor is simply moved to the lowermost row containing data. If the data source is already at the logical end of file and the browse cursor is already on the bottom row, TBrowse:hitBottom is set true (.T.).
pageUp() Repositions the data source upward
pageUp() → self
Repositions the data source upward and refills the display. If the data source is already at logical beginning of file (i.e., the topmost available record is already shown), the browse cursor is simply moved to the top data row. If the data source is already at logical beginning of file and the browse cursor is already on the first data row, TBrowse:hitTop is set true (.T.).
panEnd() Moves the cursor to the rightmost data column
panEnd() → self
Moves the browse cursor to the rightmost data column, causing the display to be panned completely to the right.
panHome() Moves the cursor to the leftmost visible data column
panHome() → self
Moves the browse cursor to the leftmost data column, causing the display to be panned all the way to the left.
panLeft() Pans left without changing the cursor position
panLeft() → self
Pans the display without changing the browse cursor, if possible. When the screen is panned with TBrowse:panLeft(), at least one data column out of view to the left is brought into view, while one or more columns are panned off screen to the right.
panRight() Pans right without changing the cursor position
panRight() → self
Pans the display without changing the browse cursor, if possible. When the screen is panned with TBrowse:panRight(), at least one data column out of view to the right is brought into view, while one or more columns are panned off the screen to the left.
Moves the browse cursor right one data column. If the cursor is already at the right edge, the display is panned and the next data column (if there is one) is brought into view.
up() Moves the cursor up one row
up() → self
Moves the browse cursor up one row. If the cursor is already on the top data row, the display is scrolled down and a new row is brought into view. If the data source is already at the logical beginning of file and the browse cursor is already on the top data row, TBrowse:hitTop is set true (.T.).
Miscellaneous Methods
addColumn() Adds a TBColumn object to the TBrowse object
addColumn(oColumn) → self
Adds a new TBColumn object to the TBrowse object and TBrowse:colCount is increased by one.
applyKey() Evaluates the code block
applyKey(nKey) → nResult
Evaluates the code block associated with nKey that is contained within the TBrowse:setKey() dictionary. nResult, which is the code block's return value, specifies the manner in which the key was processed.
TBrowse:ApplyKey() Return Values
Constant Value Meaning
TBR_EXIT -1 User request for the browse to lose input focus
TBR_CONTINUE 0 Code block associated with <nKey> was evaluated
TBR_EXCEPTION 1 Unable to locate <nKey> in the dictionary, key
was not processed
Tbrowse.ch contains manifest constants for the TBrowse:applyKey() return values.
Previously, before TBrowse:applyKey() was available, a TBrowse was typically maintained by placing an Inkey() and a case structure within a while loop. For example:
WHILE (.T.)
oTB:ForceStable() nKey := Inkey(0) DO CASE CASE (nKey == K_UP)
oTB:Up()
CASE (nKey == K_DOWN)
oTB:Down()
. . . CASE (nKey := K_ESC)
EXIT
ENDCASE
ENDDO
Because this code was external to the browse, it did not encapsulate the relationship between a key press and its effect on the browse. TBrowse:applyKey() resolves this by placing the key and its associated code block in a dictionary within the TBrowse object. This effectively makes creating and managing a browse simple, yet flexible. For example:
WHILE (.T.)
oTB:ForceStable() IF (oTB:ApplyKey(Inkey(0)) == TBR_EXIT)
EXIT
ENDIF
ENDDO
colorRect() Alters the color of a rectangular group of cells
colorRect(aRect, aColors) → self
Directly alters the color of a rectangular group of cells. aRect is an array of four numbers (top, left, bottom, and right). The numbers refer to cells within the data area of the browse display, not to screen coordinates. aColors is an array of two numbers. The numbers are used as indexes into the color table for the browse. These colors will become the normal and highlighted colors for the cells within the specified rectangle.
Cells that are colored using colorRect retain their color until they are scrolled off the screen up or down. Horizontal panning has no affect on these colors and, in fact, cells that are currently off screen left or right can be colored even if they are not visible.
This example colors the entire virtual window (on and off screen):
colWidth() Returns the display width of a particular column
colWidth(nColumn) → nWidth
Returns the display width of column number nColumn as known to the browse. If nColumn is out of bounds, not supplied, or not a number, the method returns zero.
configure() Reconfigures the internal settings of the TBrowse object
configure() → self
Causes the TBrowse object to re-examine all instance variables and TBColumn objects, reconfiguring its internal settings as required. This message can force reconfiguration when a TBColumn object is modified directly.
deHilite() Dehighlights the current cell
deHilite() → self
Causes the current cell (the cell to which the browse cursor is positioned) to be "dehighlighted." This method is designed for use when TBrowse:autoLite is set to false (.F.).
delColumn() Delete a column object from a browse
delColumn(nPos) → oColumn
This new method allows a column to be deleted from a browse. The return value is a reference to the column object being deleted, so that the column object may be preserved.
forceStable() Performs a full stabilization
forceStable()
Performs a full stabilization of the TBrowse. It is analogous to the following code, only slightly faster:
DO WHILE.NOT. oBrowse:stabilize() ENDDO
getColumn() Gets a specific TBColumn object
getColumn(nColumn) → oColumn
Returns the TBColumn object specified by nColumn.
hilite() Highlights the current cell
hilite() → self
Causes the current cell (the cell to which the browse cursor is positioned) to be highlighted. This method is designed for use when TBrowse:autoLite is set to false (.F.).
HitTest() Indicates position of mouse cursor relative to TBrowse
HitTest(nRow, nColumn) → nHitTest
Determines if the screen position specified by nRow and nColumn is on the TBrowse object.
Applicable Hit Test Return Values
Value Constant Description
0 HTNOWHERE The screen position is not within the region of
the screen that the TBrowse occupies
-1 HTTOPLEFT The screen position is on the TBrowse border's
top-left corner
-2 HTTOP The screen position is on the TBrowse's top
border
-3 HTTOPRIGHT The screen position is on the TBrowse border's
top-right corner
-4 HTRIGHT The screen position is on the TBrowse's right
border
-5 HTBOTTOMRIGHT The screen position is on the TBrowse border's
bottom-right corner
-6 HTBOTTOM The screen position is on the TBrowse's bottom
border
-7 HTBOTTOMLEFT The screen position is on the TBrowse border's
bottom-left corner
-8 HTLEFT The screen position is on the TBrowse's left
border
-5121 HTCELL The screen position is on a cell
-5122 HTHEADING The screen position is on a heading
-5123 HTFOOTING The screen position is on a footing
-5124 HTHEADSEP The screen position is on the heading separator
line
-5125 HTFOOTSEP The screen position is on the footing separator
line
-5126 HTCOLSEP The screen position is on a column separator
line
Button.ch contains manifest constants for the TBrowse:hitTest() return values.
insColumn() Insert a column object in a browse
insColumn(nPos, oColumn) → oColumn
This method allows a column object to be inserted into the middle of a browse. The return value is a reference to the column object being inserted.
invalidate() Forces redraw during next stabilization
invalidate() → self
TBrowse:invalidate() causes the next stabilization of the TBrowse object to redraw the entire TBrowse display, including headings, footings, and all data rows. Note that sending this message has no effect on the values in the data rows: it simply forces the display to be updated during the next stabilization. To force the data to be refreshed from the underlying data source, send the TBrowse:refreshAll() message.
refreshAll() Causes all data to be refreshed during the next stabilize
refreshAll() → self
Internally marks all data rows as invalid, causing them to be refilled and redisplayed during the next stabilization loop.
refreshCurrent() Causes current row to be refreshed on next stabilize
refreshCurrent() → self
Internally marks the current data row as invalid, causing it to be refilled and redisplayed during the next stabilization loop.
setColumn() Replaces one TBColumn object with another
setColumn(nColumn, oColumnNew) → oColumnCurrent
Replaces the TBColumn object indicated by nColumn with the TBColumn object specified by oColumnNew. The value returned is the current TBColumn object.
SetKey() Gets/sets a code block associated with an Inkey() value
SetKey(nKey [, bBlock]) → bPrevious
Gets and optionally sets the code block indicated by bBlock that is associated with the Inkey value specified by nKey. When replacing an existing keypress/code block definition, it returns the previous code block; otherwise, it returns the current one.
Key handlers may be queried, added, replaced, and removed from the dictionary. For example:
oTB:SetKey(K_ESC, { | oTB, nKey | TBR_EXIT })
A default key handler may be declared by specifying a value of 0 for nKey. Its associated code block will be evaluated each time TBrowse:ApplyKey() is called with a key value that is not contained in the dictionary. For example:
The example above calls a function named DefTBProc() when nKey is not contained in the dictionary.
To remove a keypress/code block definition, specify NIL for bBlock. For example:
oTB:SetKey(0, NIL }
setstyle() Maintains a dictionary within an object
setstyle(nStyle, [lSetting]) → self
TBrowse:setStyle() maintains a dictionary within a TBrowse object. This dictionary, which is simply an array, contains a set of logical values that determine behaviors associated with a TBrowse object. nStyle refers to the element in the dictionary that contains the style. lSetting indicates whether the style should be permitted or denied. Set to true (.T.) to allow the behavior to occur; otherwise, set to false (.F.) to prohibit it. CA-Clipper reserves the first four elements of the dictionary for predefined styles.
You may add custom styles to a TBrowse object by specifying any unused element of the dictionary. A maximum of 4096 definitions is available. When adding new styles to the dictionary, use the TBR_CUSTOM constant to ensure that the new styles will not interfere with the predefined ones. This guarantees that if more predefined styles are added in future releases of CA-Clipper, the positions of your styles in the dictionary will be adjusted automatically.
Styles are not utilized by the TBrowse object. The style dictionary is merely a convenient method of associating behaviors with a browse. The functions that query and implement these behaviors are external to the object. An example of this can be found in BrowSys.prg in the clip53\samples subdirectory.
TBrowse Styles
Number TBrowse.ch Meaning
1 TBR_APPEND Can the user add new information?
2 TBR_MODIFY Can the user modify the data in the browse's
cells?
3 TBR_MOVE Can the user move the column to another
position in the browse?
4 TBR_SIZE Can the user modify the width of the column?
5 TBR_CUSTOM First available element for custom styles.
Tbrowse.ch contains manifest constants for TBrowse:setStyle().
Note: TBR_MOVE and TBR_SIZE are not implemented in CA-Clipper 5.3. They are reserved for future usage.
stabilize() Performs incremental stabilization
stabilize() → lStable
Performs incremental stabilization. Each time this message is sent, some part of the stabilization process is performed. Stabilization is performed in increments so that it can be interrupted by a keystroke or other asynchronous event.
If the TBrowse object is already stable, a value of true (.T.) is returned. Otherwise, a value of false (.F.) is returned indicating that further stabilization messages should be sent. The browse is considered stable when all data has been retrieved and displayed, the data source has been repositioned to the record corresponding to the browse cursor, and the current cell has been highlighted.
Examples
For fully operational examples of a TBrowse object, refer to
"Introduction to TBrowse" in the Programming and Utilities Guide and to
TbDemo.prg located in \CLIP53\SOURCE\SAMPLE.
TEXT [TO PRINTER] [TO FILE <xcFile>]
<text>...
ENDTEXT
Arguments
text is the block of literal characters to be displayed to the screen. Text is displayed exactly as formatted.
TO PRINTER echoes the display to the printer.
TO FILExcFile echoes the display to the specified file. xcFile may be specified as a literal file name or as a character expression enclosed in parentheses. If no extension is specified, .txt is assumed.
Description
TEXT...ENDTEXT is a console command construct that displays a block of text to the screen, optionally echoing output to the printer and/or a text file. To suppress output to the screen while printing or echoing output to a file, SET CONSOLE OFF before the TEXT command line.
Text within the TEXT construct displays exactly as formatted, including any indentation. Hard carriage returns are output as new lines, soft carriage returns as the character Chr(141). Macro variables found within TEXT...ENDTEXT are expanded. However, macro expressions are not.
TEXT...ENDTEXT is a compatibility command and not recommended. CA-Clipper has other facilities for text processing and output. For example, MemoLine() in combination with MLCount() can word wrap long strings according to a specified line length. ? or @...SAY can display formatted text extracted from a long string with MemoLine().
Examples
■ This example demonstrates how to use TEXT...ENDTEXT to print a
form letter:
USE Sales NEW
DO WHILE !Eof()
FormLetter()
SKIP
ENDDO
RETURN
FUNCTION FormLetter
LOCAL dDate := DToC(Date()), cSalesman := ;
RTrim(Salesman)
TEXT TO PRINTER
&dDate.
Dear &cSalesman.,
How are you!
ENDTEXT
EJECT
RETURN NIL
Time() returns the system time as a character string in the form hh:mm:ss. hh is hours in 24-hour format, mm is minutes, and ss is seconds.
Description
Time() is a time function that displays the system time on the screen or prints it on a report. Time() is related to Seconds() which returns the integer value representing the number of seconds since midnight. Seconds() is generally used in place of Time() for time calculations.
Examples
■ These examples show the results of Time() used with SubStr()
to extract the hour, minutes, and seconds digits:
? Time() // Result: 10:37:17
? SubStr(Time(), 1, 2) // Result: 10
? SubStr(Time(), 4, 2) // Result: 37
? SubStr(Time(), 7, 2) // Result: 17
Sound a speaker tone for a specified frequency and duration
Syntax
Tone(<nFrequency>, <nDuration>) → NIL
Arguments
nFrequency is a positive numeric value indicating the frequency of the tone to be sounded.
nDuration is a positive numeric value indicating the duration of the tone measured in increments of 1/18 of a second. For example, an nDuration value of 18 represents one second.
For both arguments, non-integer values are truncated—not rounded—to their integer portion.
Returns
Tone() always returns NIL.
Description
Tone() is a sound function that indicates various program states to the user. These can be error states, boundary conditions, or the end of a time-consuming process. For example, an error state would sound an error tone before alerting the user with a message or interactive dialog box. A boundary condition might indicate that the user is attempting to move the cursor past the top or bottom of a column in a TBrowse object. A batch process also might indicate its completion with a sound to alert the user, in case the user has turned away from the screen.
Tone() works by sounding the speaker at the specified frequency for the specified duration. The duration is measured in increments of 1/18 of a second. The frequency is measured in hertz (cycles per second). Frequencies of less than 20 are inaudible. The table below shows the frequencies of standard musical notes.
Note: Tone() works only on IBM PC and 100 percent compatible computers.
Table of Musical Notes
Pitch Frequency Pitch Frequency
C 130.80 mid C 261.70
C# 138.60 C# 277.20
D 146.80 D 293.70
D# 155.60 D# 311.10
E 164.80 E 329.60
F 174.60 F 349.20
F# 185.00 F# 370.00
G 196.00 G 392.00
G# 207.70 G# 415.30
A 220.00 A 440.00
A# 233.10 A# 466.20
B 246.90 B 493.90
C 523.30
Examples
■ This example is a beep function that indicates that a batch
operation has completed:
FUNCTION DoneBeep
Tone(300, 1)
Tone(100, 1)
Tone(300, 1)
Tone(100, 1)
RETURN NIL
■ This example is a tone sequence that indicates invalid
keystrokes or boundary conditions:
FUNCTION ErrorBeep
Tone(100, 3)
RETURN NIL
Platforms
Available on MS-DOS
File
Library is EXTEND.LIB, source file is SOURCE/SAMPLE/EXAMPLEA.ASM.
The top bar menu is used as a main menu in which pop-up menus reside.
Methods link
Class Function
TopBar() Create a new TopBarMenu object
TopBar(nRow, nLeft, nRight) → oTopBar
Arguments
nRow is a numeric value that indicates the screen row of the top bar menu. This value is assigned to the TopBarMenu:row instance variable.
nLeft is a numeric value that indicates the left screen column of the top bar menu. This value is assigned to the TopBarMenu:left instance variable.
nRight is a numeric value that indicates the right screen column of the top bar menu. This value is assigned to the TopBarMenu:right instance variable.
Returns
Returns a TopBarMenu object when all of the required arguments are present; otherwise, TopBar() returns NIL.
Exported Instance Variables
cargo User-definable variable
cargo (Assignable)
Contains a value of any type that is ignored by the TopBarMenu object. TopBarMenu:cargo is provided as a user-definable slot allowing arbitrary information to be attached to a TopBarMenu object and retrieved later.
colorSpec Indicates colors used by the top bar menu's display() method
colorSpec (Assignable)
Contains a character string that indicates the color attributes that are used by the top bar menu's display() method. The string must contain six color specifiers.
TopBarMenu Color Attributes
Position Applies To Default Value from
in colorSpec System Color Setting
1 The top bar menu items that are not Unselected
selected
2 The selected top bar menu item Enhanced
3 The accelerator key for unselected top Background
bar menu items
4 The accelerator key for the selected top Enhanced
bar menu item
5 Disabled top bar menu items Standard
6 The top bar menu's border Border
Note: The colors available to a DOS application are more limited than those for a Windows application. The only colors available to you here are listed in the drop-down list box of the Properties Workbench window for that item.
current Numeric value indicating which item is selected
current (Assignable)
Contains a numeric value that indicates which item is selected.
itemCount Numeric value indicating total number of items in TopBarMenu
itemCount
Contains a numeric value that indicates the total number of items in the TopBarMenu object.
left Numeric value indicating the top bar menu's leftmost column
left (Assignable)
Contains a numeric value that indicates the top bar menu's leftmost column
right Numeric value indicating the top bar menu's rightmost column
right (Assignable)
Contains a numeric value that indicates the top bar menu's rightmost column
row Numeric value indicating row where the top bar menu appears
row (Assignable)
Contains a numeric value that indicates the row that the top bar menu appears on.
Exported Methods
addItem() Appends a new item to a top bar menu
oTopBar:addItem(oMenuItem) → self
oMenuItem is the MenuItem object to be added.
addItem() is a method of the TopBarMenu class that is used for appending a new item to a top bar menu.
delItem() Removes an item from a top bar menu
oTopBar:delItem(nPosition) → self
nPosition is a numeric value that indicates the position in the top bar menu of the item to be deleted.
delItem() is a method of the TopBarMenu class that is used for removing an item from a top bar menu. When an item is deleted, the items which follow it move up a line.
display() Shows a top bar menu and its items on the screen
oTopBar:display() → self
display() is a method of the TopBarMenu class that is used for showing a top bar menu and its items on the screen. It also shows the status bar description for menu items that contain one. display() uses the values of the following instance variables to correctly show the list in its current context, in addition to providing maximum flexibility in the manner a top bar menu appears on the screen: colorSpec, current, itemCount, left, right, and row.
Note: See the MenuModal() function in this guide for more information about displaying and activating a top menu bar.
getFirst() Determines position of the first selectable item in a menu
oTopBar:getFirst() → nPosition
Returns a numeric value that indicates the position within the top bar menu of the first selectable item. getFirst() returns 0 in the event that the top bar menu does not contain a selectable item.
getFirst() is a method of the TopBarMenu class that is used for determining the position of the first selectable item in a top bar menu. The term selectable is defined as a menu item that is enabled and whose caption is not a menu separator.
Note: getFirst() does not change the currently selected menu item. In order to change the currently selected top bar menu item, you must call the TopBarMenu:select() method.
getItem() Accesses a MenuItem object after it has been added to a menu
oTopBar:getItem(nPosition) → self
nPosition is a numeric value that indicates the position in the top bar menu of the item that is being retrieved.
getItem() is a method of the TopBarMenu class that is used for accessing a MenuItem object after it has been added to a top bar menu.
getLast() Determines position of the last selectable item in a menu
oTopBar:getLast() → nPosition
Returns a numeric value that indicates the position within the top bar menu of the last selectable item. getLast() returns 0 in the event that the top bar menu does not contain a selectable item.
getLast() is a method of the TopBarMenu class that is used for determining the position of the last selectable item in a top bar menu. The term selectable is defined as a menu item that is enabled and whose caption, is not a menu separator.
Note: getLast() does not change the currently selected menu item. In order to change the currently selected top bar menu item, you must call the TopBarMenu:select() method.
getNext() Determines position of the next selectable item in a menu
oTopBar:getNext() → nPosition
Returns a numeric value that indicates the position within the top bar menu of the next selectable item. getNext() returns 0 in the event that the current item is the last selectable item or the top bar menu does not contain a selectable item.
getNext() is a method of the TopBarMenu class that is used for determining the position of the next selectable item in a top bar menu. getNext() searches for the next selectable item starting at the item immediately after the current item. The term selectable is defined as a menu item that is enabled and whose caption is not a menu separator.
Note: getNext() does not change the currently selected menu item. In order to change the currently selected top bar menu item, you must call the TopBarMenu:select() method.
getPrev() Determines position of previous selectable item in a menu
oTopBar:getPrev() → nPosition
Returns a numeric value that indicates the position within the top bar menu of the previous selectable item. getPrev() returns 0 in the event that the current item is the first selectable item or the top bar menu does not contain a selectable item.
getPrev() is a method of the TopBarMenu class that is used for determining the position of the previous selectable item in a top bar menu. getPrev() searches for the previous selectable item starting at the item immediately before the current item. The term selectable is defined as a menu item that is enabled and whose caption is not a menu separator.
Note: getPrev() does not change the currently selected menu item. In order to change the currently selected top bar menu item, you must call the TopBarMenu:select() method.
getAccel() Determines if a key press is interpreted as a user request
oTopBar:getAccel(nInkeyValue) → nPosition
nInkeyValue is a numeric value that indicates the inkey value to be checked.
Returns a numeric value that indicates the position in the top bar menu of the first item whose accelerator key matches that which is specified by nInkeyValue. The accelerator key is defined using the & character in MenuItem:caption.
getAccel() is a method of the TopBarMenu class that is used for determining whether a key press should be interpreted as a user request to evoke the data variable of a particular top bar menu item.
HitTest() Indicates position of mouse cursor relative to menu
oTopBar:hitTest(nMouseRow, nMouseCol)
→ nHitStatus
nMouseRow is a numeric value that indicates the current screen row position of the mouse cursor.
nMouseCol is a numeric value that indicates the current screen column position of the mouse cursor.
Returns a numeric value that indicates the relationship of the mouse cursor with the top bar menu.
Hit Test Return Values
Value Constant Description
> 0 Not applicable The position in the top bar menu of the item
whose region the mouse is within
0 HTNOWHERE The mouse cursor is not within the region of
the screen that the top bar menu occupies
-1 HTTOPLEFT The mouse cursor is on the top-left corner of
the top bar menu's border
-2 HTTOP The mouse cursor is on the top bar menu's top
border
-3 HTTOPRIGHT The mouse cursor is on the top-right corner of
the top bar menu's border
-4 HTRIGHT The mouse cursor is on the top bar menu's right
border
-5 HTBOTTOMRIGHT The mouse cursor is on the bottom-right corner
the top bar menu's border
-6 HTBOTTOM The mouse cursor is on the top bar menu's
bottom border
-7 HTBOTTOMLEFT The mouse cursor is on the bottom-left corner
of the top bar menu's border
-8 HTLEFT The mouse cursor is on the top bar menu's left
border
Button.ch contains manifest constants for the TopBarMenu:hitTest() return value.
HitTest() is a method of the TopBarMenu class that is used for determining if the mouse cursor is within the region of the screen that the Top bar menu occupies.
insItem() Inserts a new item in a top bar menu
oTopBar:insItem(nPosition, oMenuItem) → self
nPosition is a numeric value that indicates the position at which the new menu item is inserted.
oMenuItem is the MenuItem object to be inserted.
insItem() is a method of the TopBarMenu class that is used for inserting a new item in a top bar menu.
nPosition indicates the position in the top bar menu of the item to be selected.
Select() is a method of the TopBarMenu class that is used for changing the selected item. Its state is typically changed when one of the arrow keys is pressed or the mouse's left button is pressed when its cursor is within the top bar menu's screen region.
setItem() Replaces a MenuItem object after it has been added to a menu
oTopBar:setItem(nPosition, oMenuItem) → self
nPosition is a numeric value that indicates the position in the top bar menu of the item that is being retrieved.
oMenuItem is the MenuItem object that replaces the one in the top bar menu specified by nPosition.
setItem() is a method of the TopBarMenu class that is used for replacing a MenuItem object after it has been added to a top bar menu. After the setItem() method is called, the display() method needs to be called in order to refresh the menu.
Examples
See the Menu.prg sample file in the \CLIP53\SOURCE\SAMPLE directory.
This example demonstrates combining TopBarMenu, PopUpMenu, and MenuItem
objects to create a menu with a number of available choices. See
"Introduction to the Menu System" in the Programming and Utilities Guide
for more information about using this class.
Summarize records by key value to a database (.dbf) file
Syntax
TOTAL ON <expKey> [FIELDS <idField list>]
TO <xcDatabase>
[<scope>] [WHILE <lCondition>] [FOR <lCondition>]
Arguments
ONexpKey defines the group of records that produce a new record in the target database file. To make the summarizing operation accurate, the source database file should be INDEXed or SORTed on this expression.
FIELDSidField list specifies the list of numeric fields to TOTAL. If the FIELDS clause is not specified, no numeric fields are totaled. Instead each numeric field in the target file contains the value for the first record matching the key expression.
TOxcDatabase is the name of the target file that will contain the copy of the summarized records. Specify this argument as a literal file name or as a character expression enclosed in parentheses. Unless otherwise specified, TOTAL assumes a .dbf extension.
scope is the portion of the current database file to TOTAL. The default is ALL records.
WHILElCondition specifies the set of records meeting the condition from the current record until the condition fails.
FORlCondition specifies the conditional set of records to TOTAL within the given scope.
Description
TOTAL is a database command that sequentially processes the current database file, summarizing records by the specified key value and copying them to a new database file. TOTAL works by first copying the structure of the current database file to xcDatabase, except for memo fields. It then sequentially scans the current database file within the specified scope of records. As each record with a unique expKey value is encountered, that record is copied to the new database file. The values of numeric fields specified in idField list from successive records with the same expKey value are added to fields with the same names in xcDatabase. Summarization proceeds until a record with a new key value is encountered. The process is then repeated for this record.
Since TOTAL processes the source database file sequentially, it must be INDEXed or SORTed in expKey order for the summarization to be correct.
To successfully TOTAL numeric fields, the source numeric fields must be large enough to hold the largest total possible for that numeric field. If not, a runtime error is generated.
Notes
■ Deleted source records: If DELETED is OFF, deleted records in
the source file are TOTALed. Records in the target xcDatabase inherit the deleted status of the first matching record in the source file, just as nontotaled fields inherit their values. If DELETED is ON, however, none of the deleted source records are TOTALed.
Examples
■ In this example, a database file is TOTALed ON the key
expression of the controlling index using a macro expression. When
the macro expression is encountered, the expression is evaluated and
the resulting character string is substituted for the TOTAL <expKey>
argument:
USE Sales INDEX Branch NEW
TOTAL ON &(IndexKey(0)) FIELDS Amount TO Summary
Convert any value into a formatted character string
Syntax
Transform(<exp>, <cSayPicture>) → cFormatString
Arguments
exp is the value to be formatted. This expression can be any valid CA-Clipper data type except array, code block, and NIL.
cSayPicture is a string of picture and template characters that describes the format of the returned character string.
Returns
Transform() converts exp to a formatted character string as defined by cSayPicture.
Description
Transform() is a conversion function that formats character, date, logical, and numeric values according to a specified picture string that includes a combination of picture function and template strings. Transform() formats data for output to the screen or the printer in the same manner as the PICTURE clause of the @...SAY command.
■ Function string: A picture function string specifies
formatting rules that apply to the Transform() return value as a whole, rather than to particular character positions within exp. The function string consists of the @ character, followed by one or more additional characters, each of which has a particular meaning (see table below). If a function string is present, the @ character must be the leftmost character of the picture string, and the function string must not contain spaces. A function string may be specified alone or with a template string. If both are present, the function string must precede the template string, and the two must be separated by a single space.
Transform() Functions
Function Action
B Displays numbers left-justified
C Displays CR after positive numbers
D Displays date in SET DATE format
E Displays date in British format
R Nontemplate characters are inserted
X Displays DB after negative numbers
Z Displays zeros as blanks
( Encloses negative numbers in parentheses
! Converts alphabetic characters to uppercase
■ Template string: A picture template string specifies
formatting rules on a character-by-character basis. The template string consists of a series of characters, some of which have special meanings (see table below). Each position in the template string corresponds to a position in the value of the exp argument. Because Transform() uses a template, it can insert formatting characters such as commas, dollar signs, and parentheses.
Characters in the template string that have no assigned meanings are copied literally into the return value. If the @R picture function is used, these characters are inserted between characters of the return value; otherwise, they overwrite the corresponding characters of the return value. A template string may be specified alone or with a function string. If both are present, the function string must precede the template string, and the two must be separated by a single space.
Transform() Templates
Template Action
A,N,X,9,# Displays digits for any data type
L Displays logicals as "T" or "F"
Y Displays logicals as "Y" or "N"
! Converts an alphabetic character to uppercase
$ Displays a dollar sign in place of a leading space in a
numeric
* Displays an asterisk in place of a leading space in a
numeric
. Specifies a decimal point position
, Specifies a comma position
Examples
■ This example formats a number into a currency format using a
template:
? Transform(123456, "$999,999") // Result: $123,456
■ This example formats a character string using a function:
? Transform("to upper", "@!") // Result: TO UPPER
cString is the character string to be copied without trailing spaces.
Returns
Trim() returns a copy of cString with the trailing spaces removed. If cString is a null string ("") or all spaces, Trim() returns a null string ("").
Description
Trim() is a character function that formats character strings. It is useful when you want to delete trailing spaces while concatenating strings. This is typically the case with database fields which are stored in fixed-width format. For example, you can use Trim() to concatenate first and last name fields to form a name string.
Trim() is related to LTrim(), which removes leading spaces, and AllTrim(), which removes both leading and trailing spaces. The inverse of AllTrim(), LTrim(), and RTrim() are the PadC(), PadR(), and PadL() functions which center, right-justify, or left-justify character strings by padding them with fill characters.
Notes
■ Space characters: The Trim() function treats carriage
returns, line feeds, and tabs as space characters and removes these as well.
Examples
■ This is a user-defined function in which Trim() formats city,
state, and zip code fields for labels or form letters:
FUNCTION CityState(cCity, cState, cZip)
RETURN Trim(cCity) + ", " ;
+ Trim(cState) + " " + cZip
■ In this example the user-defined function, CityState(),
displays a record from Customer.dbf:
USE Customer INDEX CustName NEW
SEEK "Kate"
? CityState(City, State, ZipCode)
// Result: Athens, GA 10066
cExp is a character expression whose type is to be determined. cExp can be a field, with or without the alias, a private or public variable, or an expression of any type.
Returns
Type() returns one of the following characters:
Type() Return Values
Returns Meaning
A Array
B Block
C Character
D Date
L Logical
M Memo
N Numeric
O Object
U NIL, local, or static
UE Error syntactical
UI Error indeterminate
Description
Type() is a system function that returns the type of the specified expression. It can test expression validity as long as the expression uses CLIPPER.LIB functions and does not reference local or static variables, user-defined functions, or built-in functions supplied in EXTEND.LIB.
Type() is like ValType() but uses the macro operator (&) to determine the type of the argument. This precludes the use of Type() to determine the type of local and static variables. ValType(), by contrast, evaluates an expression and determines the data type of the return value. This lets you determine the type of user-defined functions as well as local and static variables.
Notes
■ Array references: References to private and public arrays
return "A." References to array elements return the type of the element.
■ IF(): To return the appropriate data type for an IF()
expression, Type() evaluates the condition, and then, returns the type of the evaluated path. If either the IF() condition or the evaluated path are invalid, Type() returns "UE."
■ Testing parameters: Type() can only test the validity of
parameters received using the PARAMETERS statement. Testing a parameter declared as part of a FUNCTION or PROCEDURE declaration always returns "U" because local parameters do not have a symbol in the symbol table. To determine whether an argument was skipped or left off the end of the argument list, compare the parameter to NIL or use ValType().
■ User-defined and EXTEND.LIB functions: If a reference is made
anywhere in an expression to a function not found in CLIPPER.LIB (a user-defined or EXTEND.LIB function), Type() returns "UI." If the user-defined function is not linked into the current program, Type() returns "U."
Examples
■ These examples demonstrate various results from invocations of
Type():
? Type('SubStr("Hi There", 4, 5)') // Result: C
? Type("UDF()") // Result: UI
? Type('IF(.T., "true", 12)') // Result: C
■ This example shows two methods for testing for the existence
and type of declared parameters:
FUNCTION TestParams
PARAMETERS cParam1, nParam2
IF cParam1 = NIL
? "First parameter was not passed"
cParam1 := "Default value"
ENDIF
IF Type('nParam2') == "U"
? "Second parameter was not passed"
ENDIF
.
. <statements>
.
RETURN NIL
xcFile is the name of the file, including extension, to be displayed to the screen. This argument may be specified as a literal file name or as a character expression enclosed in parentheses. xcFile must be specified with an extension if it has one.
TO PRINTER echoes the display to the printer.
TO FILExcOutFile echoes the display to the specified file. xcOutFile may be specified either as a literal file name or as a character expression enclosed in parentheses. If no extension is specified, .txt is added.
Description
TYPE is a console command that displays the contents of a text file to the screen, optionally echoing the display to the printer and/or another text file. To suppress output to the screen while printing or echoing output to a file, SET CONSOLE OFF before the TYPE invocation.
If xcFile is specified without a path and/or drive designator, TYPE searches the current DEFAULT directory, and then, the current PATH. If xcOutFile is specified without a path and/or drive designator, TYPE creates the file in the current DEFAULT directory.
TYPE performs no special formatting on the listing. There are no special headings or pagination when the output is sent to the printer.
To pause output, use Ctrl-S. Note that you cannot interrupt a listing with Esc.
Examples
■ This example illustrates the TYPE command:
TYPE Main.prg TO PRINTER
ALL releases all current locks in all work areas. If not specified, only the lock in the current work area is released.
Description
UNLOCK is a network command that releases file or record locks set by the current user. Use it when you want to release the current lock without setting a new lock. Both FLock() and RLock() release the current lock before setting a new one.
After an UNLOCK, an update to a shared database file and associated index and memo files becomes visible to DOS and other applications, but is not guaranteed to appear on disk until you perform a COMMIT or close the file.
Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information on the principles of locking and update visibility.
Notes
■ SET RELATION: UNLOCK does not automatically release a record
lock along a RELATION chain unless you UNLOCK ALL.
Examples
■ This example attempts an update operation that requires a
record lock. If the RLock() is successful, the record is updated
with a user-defined function and the RLock() is released with UNLOCK:
USE Sales INDEX Salesman SHARED NEW
IF RLock()
UpdateRecord()
UNLOCK
ELSE
? "Record update failed"
BREAK
ENDIF
Updated() returns true (.T.) if data in a GET is added or changed; otherwise, it returns false (.F.).
Description
Updated() determines whether characters were successfully entered into a GET from the keyboard during the most current READ. Each time READ executes, Updated() is set to false (.F.). Then, any change to a GET entered from the keyboard sets Updated() to true (.T.) after the user successfully exits the GET. If the user presses Esc before exiting the first GET edited, Updated() remains false (.F.). Once Updated() is set to true (.T.), it retains this value until the next READ is executed.
Within a SET KEY or VALID procedure, you can change the current GET variable using the KEYBOARD command or by assigning a new value with one of the many assignment operators. Changing the variable with KEYBOARD is the same as if the user had entered the change directly from the keyboard, and Updated() is set accordingly. However, since Updated() reflects only those changes made from the keyboard, an assignment to the GET variable does not affect Updated().
Examples
■ This example assigns field values from Customer.dbf to
variables and edits them. If the user changes any of the values, the
field variables for the current record are updated with the new
values:
USE Customer NEW
CLEAR
MEMVAR->Customer = Customer->Customer
MEMVAR->Address = Customer->Address
@ 1, 1 SAY "Name:" GET MEMVAR->Customer
@ 2, 1 SAY "Address:" GET MEMVAR->Address
READ
//
IF Updated()
Customer->Customer := MEMVAR->Customer
Customer->Address := MEMVAR->Address
ENDIF
Upper() returns a copy of cString with all alphabetical characters converted to uppercase. All other characters remain the same as in the original string.
Description
Upper() is a character function that converts lowercase and mixed case strings to uppercase. It is related to Lower() which converts uppercase and mixed case strings to lowercase. Upper() is related to the IsUpper() and IsLower() functions which determine whether a string begins with an uppercase or lowercase letter.
Upper() is generally used to format character strings for display purposes. It can, however, be used to normalize strings for case- independent comparison or INDEXing purposes.
Examples
■ These examples illustrate the effects of Upper():
? Upper("a string") // Result: A STRING
? Upper("123 char = <>") // Result: 123 CHAR = <>
■ This example uses Upper() as part of a case-independent
condition:
USE Customer INDEX CustName NEW
LIST CustName FOR "KATE" $ Upper(Customer)
■ Upper() is also useful for creating case-independent index key
expressions:
USE Customer NEW
INDEX ON Upper(Last) TO CustLast
■ Later, use the same expression to look up Customers:
MEMVAR->Last = Space(15)
@ 10, 10 GET MEMVAR->Last
READ
SEEK Upper(MEMVAR->Last)
Update current database file from another database file
Syntax
UPDATE FROM <xcAlias>
ON <expKey> [RANDOM]
REPLACE <idField> WITH <exp>
[, <idField2> WITH <exp2>...]
Arguments
FROMxcAlias specifies the alias of the work area used to update records in the current work area. This argument may be specified either as a literal file name or as a character expression enclosed in parentheses.
ONexpKey specifies the expression that defines matching records in the FROM work area.
REPLACEidField specifies a field in the current work area to replace with a new value.
WITHexp specifies the value to replace into the current field. You must reference any field contained in the FROM work area with the correct alias.
RANDOM allows records in the FROM database file to be in any order. If this option is specified, the current database file must be indexed on expKey.
Description
UPDATE is a database command that replaces fields in the current work area with values from another work area based on the specified key expression. UPDATE is designed to update only current work area records based on a one-to-one or one-to-many relation with the FROM work area. This means that UPDATE can only update records in the current work area with unique key values. When there is more than one instance of a key value, only the first record with the key value is updated. The FROM work area, however, can have duplicate key values.
There are two formulations of the command depending on whether the FROM work area records are sorted or indexed on expKey or not. If RANDOM is not specified, both the current work area and the FROM work area must be indexed or sorted in expKey order. If RANDOM is specified, the current work area must be indexed by expKey, but the FROM work area records can be in any order.
To use UPDATE in a network environment, the current database file must be locked with FLock() or USEed EXCLUSIVEly. The FROM database file may be used in any mode. Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information.
Notes
■ Deleted records: If DELETED is OFF, deleted records in both
source files are processed. Records in the file being updated retain their deleted status and are not affected by the deleted status of records in the FROM file. If DELETED is ON, however, no deleted records are processed from either source file.
Examples
■ This example UPDATEs the Customer database file with
outstanding invoice amounts:
USE Invoices NEW
USE Customer INDEX Customer NEW
UPDATE FROM Invoices ON Last;
REPLACE Owed WITH Owed + Invoices->Amount RANDOM
Used() returns true (.T.) if there is a database file in USE; otherwise, it returns false (.F.).
Description
Used() is a database function that determines whether there is a database file in USE in a particular work area. By default, Used() operates on the currently selected work area. It will operate on an unselected work area if you specify it as part of an aliased expression.
Examples
■ This example determines whether a database file is in USE in
the current work area:
USE Customer NEW
? Used() // Result: .T.
CLOSE
? Used() // Result: .F.
xcDatabase is the name of the database file to be opened and may be specified either as a literal file name or as a character expression enclosed in parentheses.
INDEXxcIndex list specifies the names of 1 to 15 index files to be opened in the current work area. Specify each index as a literal file name or as a character expression enclosed in parentheses. The first index in the list becomes the controlling index. If you specify an xcIndex as an expression and the value returned is spaces or NIL, it is ignored.
ALIASxcAlias specifies the name to associate with the work area when the database file is opened. You may specify the alias name as a literal name or as a character expression enclosed in parentheses. A valid xcAlias may be any legal identifier (i.e., it must begin with an alphabetic character and may contain numeric or alphabetic characters and the underscore). Within a single application, CA-Clipper will not accept duplicate aliases. If this clause is omitted, the alias defaults to the database file name.
EXCLUSIVE opens the database file for nonshared use in a network environment. All other users are denied access until the database file is CLOSEd.
SHARED opens the database file for shared use in a network environment. Specifying this clause overrides the current EXCLUSIVE setting.
NEW opens xcDatabase in the next available work area making it the current work area. If this clause is not specified, xcDatabase is opened in the current work area.
READONLY opens xcDatabase with a read-only attribute. This lets you open database files marked read-only. If you cannot open the xcDatabase this way, a runtime error is generated. If this clause is not specified, xcDatabase is opened as read-write.
VIA cDriver specifies the replaceable database driver (RDD) with which to process the current work area. cDriver is the name of the RDD specified as a character expression. If cDriver is specified as a literal value, it must be enclosed in quotes.
If the VIA clause is omitted, the DBFNTX driver is used by default. Note that if the specified driver is not linked, an unrecoverable error occurs.
In no arguments are specified, the database file open in the current work area is closed.
Description
USE opens an existing database (.dbf) file, its associated memo (.dbt) file, and optionally associated index (.ntx or .ndx) file(s) in the current or the next available work area. In CA-Clipper, there are 250 work areas with a maximum of 255 total files open in DOS 3.3 and above. Before USE opens a database file and its associated files, it closes any active files already open in the work area. When a database file is first opened, the record pointer is positioned at the first logical record in the file (record one, if there is no index file specified).
In a network environment, you may open database files as EXCLUSIVE or SHARED. EXCLUSIVE precludes the USE of the database file by other users until the file is closed. SHARED allows other users to USE the database file for concurrent access. If the database file is SHARED, responsibility for data integrity falls upon the application program. In CA-Clipper, FLock() and RLock() are the two basic means of denying other users access to a particular work area or record. If a USE is specified and neither EXCLUSIVE nor SHARED is specified, the database file is opened according to the current EXCLUSIVE setting. In CA-Clipper, all USE commands should explicitly specify how the database file is to be opened, EXCLUSIVE or SHARED. The implicit open mode specified by SET EXCLUSIVE is supplied for compatibility purposes only and not recommended.
Opening a database file in a network environment requires some special handling to be successful. First, attempt to USE the database file without specifying the INDEX list. Then, test for the success of the operation using NetErr(). If NetErr() returns false (.F.), the open operation succeeded and you can SET INDEX TO the index list. A USE will fail in a network environment if another user has EXCLUSIVE USE of the database file. Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information on opening files in a network environment.
You can open index files with USE or SET INDEX. The first index in the list of indexes defines the current ordering of records when they are accessed. This index is referred to as the controlling index. You can change the current controlling index without closing any files by using the SET ORDER command.
To close a database and its associated files in the current work area, specify USE or CLOSE with no arguments. To close database files in all work areas, use CLOSE DATABASEs. To close index files in the current work area without closing the database file, use CLOSE INDEX or SET INDEX TO with no arguments.
Refer to the "Basic Concepts" chapter in the Programming and Utilities Guide for more information about the CA-Clipper database paradigm.
Notes
■ Setting the maximum open files: Control of the number of file
handles available to a CA-Clipper application is controlled by a combination of the CONFIG.SYSFILES command, and the F parameter of the CLIPPER environment variable. The F parameter specifies the maximum number of files that can be opened at any one time within the current CA-Clipper program. CA-Clipper determines the number of files that can be opened using the smaller of the two parameters. For example, if the FILES command is set to 120 and the F parameter is set to 50, the maximum number of files that can be opened is 50. In a network environment, file handles also need to be set in the network configuration file.
The file limit is controlled by the operating system. Under DOS versions less than 3.3, the maximum number of files that can be opened at one time is 20 files. In DOS versions 3.3 and greater, the maximum limit is 255 files.
■ Opening the same database file in more than one work area:
Although opening a database file in more than one work area is possible in a network environment, this practice is strongly discouraged. If done, each file must be opened with a different alias, otherwise a runtime error will occur.
■ Opening two database files with the same names, in different
directories: Although opening two database files with the same names in different directories is possible, the database files MUST have unique alias names; otherwise, a runtime error will occur.
Examples
■ This example opens a shared database file with associated
index files in a network environment. If NetErr() returns false
(.F.), indicating the USE was successful, the indexes are opened:
USE Accounts SHARED NEW
IF !NetErr()
SET INDEX TO AcctNames, AcctZip
ELSE
? "File open failed"
BREAK
ENDIF
■ This example opens a database file with several indexes
specified as extended expressions. Note how the array of index names
is created as a constant array:
xcDatabase = "MyDbf"
xcIndex = {"MyIndex1", "MyIndex2", "MyIndex3"}
USE (xcDatabase) INDEX (xcIndex[1]), ;
(xcIndex[2]), (xcIndex[3])
cNumber is the character expression to be converted.
Returns
Val() returns cNumber converted to a numeric value including decimal digits.
Description
Val() is a character conversion function that converts a character string containing numeric digits to a numeric value. When Val() is executed, it evaluates cNumber until a second decimal point, the first non-numeric character, or the end of the expression is encountered. Leading spaces are ignored. When SET FIXED is ON, Val() returns the number of decimal places specified by SET DECIMALS, rounding cNumber if it is specified with more digits than the current DECIMALS value. As with all other functions that round, digits between zero and four are rounded down, and digits between five and nine are rounded up. When SET FIXED is OFF, Val() returns the number of decimal places specified in cNumber.
Val() is the opposite of Str() and Transform(), which convert numeric values to character strings.
Examples
■ These examples illustrate Val() with SET FIXED ON and SET
DECIMALS TO 2:
SET DECIMALS TO 2
SET FIXED ON
//
? Val("12.1234") // Result: 12.12
? Val("12.1256") // Result: 12.13
? Val("12A12") // Result: 12
? Val("A1212") // Result: 0
? Val(Space(0)) // Result: 0
? Val(Space(1)) // Result: 0
? Val(" 12.12") // Result: 12.12
ValType() returns a single character representing the data type returned by exp. ValType() returns one of the following characters:
ValType() Return Values
Returns Meaning
A Array
B Block
C Character
D Date
L Logical
M Memo
N Numeric
O Object
U NIL
Description
ValType() is a system function that takes a single argument, evaluates it, and returns a one-character string describing the data type of the return value. It is similar to Type(), but differs by actually evaluating the specified argument and determining the type of the return value. For this reason, you can determine the type of local and static variables, user-defined functions, and EXTEND.LIB functions. Type(), by contrast, uses the macro operator (&) to evaluate the type of its argument. Note that if the argument does not exist, an error ("undefined error") will occur, unlike TYPE which will return "U."
Examples
■ These examples show the return values for several data types:
? ValType(1) // Result: N
? ValType("GOOB") // Result: C
? ValType(NIL) // Result: U
? ValType(array) // Result: A
? ValType(block) // Result: B
expPrompt is an expression of any data type displayed as a prompt. If no expPrompt is specified, the default prompt displayed is: "Press any key to continue..."
TOidVar is the variable, of any storage class, that holds the value of the key pressed as a character value. If idVar does not exist or is not visible, it is created as a private variable and then assigned the character value.
Description
WAIT is a console command and wait state that displays a prompt after sending a carriage return/line feed to the screen. It then waits for the user to press a key. If the TO clause is specified, idVar is assigned the keystroke as a character value. If an Alt or Ctrl key is pressed, WAIT assigns Chr(0) to idVar. Non-alphanumeric values entered by pressing an Alt-keypad combination assign the specified character. If the character can be displayed, it is echoed to the screen. Function keys are ignored unless assigned with SET FUNCTION or SET KEY.
WAIT is a compatibility command and, therefore, is not recommended for general usage. It is superseded by both @...GET/READ and Inkey() for getting single character input.
Notes
■ WAITing without a prompt: To pause execution without
displaying a prompt, specify WAIT, null string (""), or Inkey(0). The latter is recommended since it does not disturb the current screen cursor position.
Examples
■ This example illustrates how to store the WAIT keystroke as an
array element:
aVar := Array(6)
WAIT "Press a key..." TO aVar[1]
? aVar[1] // Result: key pressed in
// response to WAIT
? aVar[2] // Result: NIL
? ValType(aVar) // Result: A
? ValType(aVar[1]) // Result: C
Convert CALL command numeric parameters from double to integer values
Syntax
Word(<nNumber>) → NIL
Arguments
nNumber is the numeric value to be converted to an integer specified in the range of plus or minus 32,767, inclusive.
Returns
Used as an argument for the CALL command, Word() returns an integer. In all other contexts, it returns NIL.
Description
Word() is a numeric conversion function that converts numeric parameters of the CALL command from double to integer values. Word() is a compatibility command and, therefore, not recommended. Both the CALL command and the Word() function are superseded by facilities provided by the Extend System. Refer to the "Using the Extend System" chapter in the Technical Reference Guide for more information.
Examples
■ This example uses Word() as an argument of the CALL command:
CALL Cproc WITH Word(30000), "Some text"
Convert a date value to the year as a numeric value
Syntax
Year(<dDate>) → nYear
Arguments
dDate is the date value to be converted.
Returns
Year() returns the year of the specified date value including the century digits as a four-digit numeric value. The value returned is not affected by the current DATE or CENTURY format. Specifying a null date (CToD("")) returns zero.
Description
Year() is a date conversion function that converts a date value to a numeric year value. Use it in calculations for things like periodic reports or for formatting date displays.
Year() is a member of a group of functions that return components of a date value as numeric values. The group includes Day() and Month() which return the day and month values as numeric values.
Examples
■ These examples illustrate Year() using the system date:
? Date() // Result: 09/20/90
? Year(Date()) // Result: 1990
? Year(Date()) + 11 // Result: 2001
■ This example creates a user-defined function using Year() to
format a date value in the following form: month day, year.
? MDY(Date()) // Result: September 20, 1990
FUNCTION MDY( dDate )
RETURN CMonth(dDate) + " " + ;
LTrim(Str(Day(dDate)));
+ "," + Str(Year(dDate))
ZAP is a database command that permanently removes all records from files open in the current work area. This includes the current database file, index files, and associated memo file. Disk space previously occupied by the ZAPped files is released to the operating system. ZAP performs the same operation as DELETE ALL followed by PACK, but is almost instantaneous in comparison.
To ZAP in a network environment, the current database file must be USEd EXCLUSIVEly. Refer to the "Network Programming" chapter in the Programming and Utilities Guide for more information.
Examples
■ This example demonstrates a typical ZAP operation in a network
environment:
USE Sales EXCLUSIVE NEW
IF !NetErr()
SET INDEX TO Sales, Branch, Salesman
ZAP
CLOSE Sales
ELSE
? "Zap operation failed"
BREAK
ENDIF
Blue B 1 Underline │ Bright Blue B+ 9 Bright Underline
Green G 2 White │ Bright Green G+ 10 Bright White
Cyan BG 3 White │ Bright Cyan BG+ 11 Bright White
Red R 4 White │ Bright Red R+ 12 Bright White
Magenta RB 5 White │ Bright Magenta RB+ 13 Bright White
Brown GR 6 White │ Yellow GR+ 14 Bright White
White W 7 White │ Bright White W+ 15 Bright White
Black U Underline
Inverse I Inverse video
Black X Blank
? Note
If numbers are used and the background color is greater than 7, the foreground color is displayed blinking. If letters are used and the high intensity attribute is applied to the background color, the foreground color is displayed in high intensity.