Internal Functions

From BR Wiki
Revision as of 10:20, 3 February 2012 by Mikhail.zheleznov (talk | contribs)
Jump to navigation Jump to search

BR has numerous built-in internal functions that return either numeric or string values. By using internal functions for tasks such as searching or summing an array, both programmers and programs can be more efficient in getting their jobs done. Numeric functions may be used anywhere that a numeric expression is valid. Likewise, string functions may be used anywhere that a string expression is valid. Internal functions usually perform generic tasks often needed by programmers.

This section presents these internal functions in alphabetical order. Their purpose is described, comments and examples are provided and related functions are mentioned.

Note that this is the 4th section of the BR Reference. Many of the topics involved in discussing BR Internal Functions may not have been discussed yet. Most likely you will come back to this section often as you learn more and more BR material.

Syntax Conventions

Numeric values are symbolized by the variables X and Y. String variables are symbolized by A$, B$, and C$. File reference numbers are symbolized by N, where N is the number associated with an opened file. Square brackets around a parameter indicate the parameter is optional. In all cases, the parameters or arguments which are passed remain unchanged.

ABS

ABS(<numeric expression>)

The Abs internal function returns the absolute value of the numeric expression within parenthesis. In other words, regardless of whether the argument passed to ABS is positive, zero, or negative, the result is always NON-NEGATIVE.

Comments and Examples

  • ABS(-342) returns 342
  • ABS(-84.11) returns 84.11
  • ABS(4) returns 4
  • ABS(0) returns 0

Related Functions


AIDX

AIDX (<array name>)

The AIDX internal function returns an array that is an ascending index obtained from sorting the array within parenthesis. The array to be sorted may be either string or numeric. The use of AIDX is permitted only in the MAT statement.

Note that you cannot use the Mat keyword in the array name parameter of this function.

Correct:

00010 MAT AscendingIndexArray(UDIM(ArrayToBeIndexed$))=AIDX(ArrayToBeIndexed$)

Incorrect:

00010 MAT AscendingIndexArray(UDIM(ArrayToBeIndexed$))=AIDX(MAT ArrayToBeIndexed$)

Comments and Examples

The program below will sort and print an array of names in alphabetical order:

00100 DIM A(100),N$(100)
00110 DATA "Tom", "Colleen", "Bill", "Christi"
00120 DATA "Tim", "Dave", "Sheila", "Jenni"
00130 DATA "Pam", "Laura", "Jean", "Michele"
00140 DATA "Gary", "Gordon", "Mallika"
00150 READ MAT N$ EOF 155
00155 MAT N$(CNT)
00160 MAT A(UDIM(N$))=AIDX(N$) ! 
00170 FOR I=1 TO 15
00180    PRINT N$(A(I))
00190 NEXT I

Related Functions

Other functions that operate on arrays are DIDX (array sort with descending index), SRCH, SUM and UDIM. See also MAT.

Technical Considerations

  1. The RD specification in BRConfig.sys can affect the AIDX function because it determines when two numeric values are considered equal.
  2. The COLLATE option in effect when the program was last saved or in the Option (statement) can alter the sort order from the AIDX function when sorting string values.
  3. To use AIDX, the arrays on both sides of the equal sign must have only one dimension and they must be the same number of elements.


ATN

ATN(<numeric expression>)

The Atn internal function is a trigonometric function that calculates the arctangent of the numeric expression in radians.

Example

00010 print ATN(3.4)

Output:

1.284745

Related Functions


BELL

BELL

The BELL internal function returns a character which, when printed, sounds the printer's or terminal's bell. It is used mainly in PRINT statements.

Comments and Examples

00010 PRINT BELL
00020 PRINT #255: BELL, BELL, BELL
00030 PRINT BELL;
00040 PRINT BELL, NEWPAGE, "ERROR"

Line 10 causes a tone or beep to sound at the terminal. Line 20 causes the printer's bell (if it has one) to sound three times. Line 30 produces a beep at the terminal, but keeps the cursor on the same line; this variation is often useful with full screen processing. Line 40 sounds the tone, clears the screen and prints the message ERROR at the bottom of the screen.

Related Functions

Technical Considerations

  1. In an unformatted PRINT statement, when BELL precedes the TAB(X) function, the TAB function will appear to be off by one column because the character for BELL appears in the output buffer, but not on the screen or printer. Avoid using BELL (or NEWPAGE) before TAB in an unformatted PRINT statement. One remedy is to use one PRINT statement for BELL (and NEWPAGE) and another for the TAB function and other output.


CEIL

Ceil(<numeric expression>)

The Ceil internal function calculates the smallest integer greater than or equal to X.

In simplest terms, Ceil always rounds up.

Comments and Examples

CEIL(+5.1) is 6, but CEIL(-5.1) is -5.

Related Functions


CFORM$

CFORM$(<form statement>) 

The CFORM$ internal function clears the way for programs to use a variable for I/O format without the performance drawbacks that are typically associated with this usage.

In the past, use of a variable for I/O formatting, as in the statement has been discouraged because the FORM string must be compiled on each execution of the READ statement. The CFORM$ string contains the format information that would otherwise be specified in a FORM statement.

Example:

00010 dim formstring$*1000, id$*5, name$*30
00020 let formstring$ = CFORM$("FORM pos 1,C 5,C 30,2*N 5")
00030 READ #1 USING formstring$: id$, name$, age, weight

The CFORM$ function allows programs to "compile" format variables prior to their use. In the following sample code fragment, the contents of A$ are compiled by CFORM$ and reassigned to A$. This is done prior to the execution of a loop where A$ is used as the format variable. This speeds up execution because the FORM statement is not compiled in every execution of the FOR loop:

00900 let A$="FORM C 10, V 20, BH 3"
01000 let A$=CFORM$(A$)
01010 FOR X=1 TO 100
01020    READ #1,USING A$: Variables
01030 NEXT X

Below is a slower version of the above example. In this slower version, the FORM statement is hard-coded into the FOR loop and compiled by BR every time the loop executes. This is much slower than compiling it once using the CFORM$ function before executing the FOR loop.

01010 FOR X=1 TO 100
01020    READ #1,USING "FORM C 10, V 20, BH 3": Variables
01030 NEXT X

NOTE that variables compiled by CFORM$ will be in an unreadable, machine-dependent internal format. Therefore, programs should never compile a format with CFORM$ and save it to a file for use by other programs. The output of CFORM$ can vary with each machine and with each release of BR.

Be aware that compiled FORM statements that reference variables do so by pointing to the relative dictionary entry, not the name of the variable. This means that when I use CFORM$ to compile a FORM statement and that FORM statement points to a variable for a length or decimal position specification, then that compiled FORM may point to an altogether different variable in a library, or could even point beyond the dictionary in the library, possibly destabilizing BR.

Consider the following example:

1000 Let QTY_FORM$= CFORM$("FORM C 10, V 20, BH 4.QTY_DEC, BH 3")

where QTY_DEC holds the number of decimal positions in inventory quantities. Let's postulate that QTY_DEC is the fifth dictionary entry.

If QTY_FORM$ is passed to a library, the reference to QTY_DEC would point to the fifth dictionary entry in the library which typically would not correlate with QTY_DEC.

The work around to this would be to begin both the calling program and the library with DIM QTY_DEC and recompile both programs. This would compile QTY_DEC as the first dictionary entry in both programs.


CHR$

CHR$(<numeric expression>)

The Chr$ internal function returns the ASCII character represented by the numeric expression, which may have an integer value from 0 to 255.

Comments and Examples

Chr$ is often used to send special characters to control a printer or screen. Chr$(27) generates the same ASCII character as the Esc key.

In order to see the different characters which the CHR$ function can produce, run the following example:

00010 for i = 1 to 255
00020    print CHR$(i);
00030 next i

Output:

Note that the semicolon after the print statement forces the carriage return not to be printed after each character. As a result, we are able to see all of our output on just a few lines which fit nicely on one screen. Without this semicolon we would only be able to see 24 rows of output at a time.

NWP Printing

CHR$(6) implies right justify the previous field for printed output. This works just like \Eright_justify except \Eright_justify applies to the following text whereas CHR$(6) pertains to the preceding text.

Related Functions

Inverse function is Ord(A$). Hex$ function can send several special codes in one function call.

Technical Considerations

  1. If the parameter value is greater than 255, only the low order byte will be used. Thus, CHR$(65) and CHR$(65+256) both will print the letter A.


CMDKEY

The CMDKEY internal function returns a value to identify the last command key (function key) used to terminate keyboard input, or returns 0 if <ENTER> was the last key pressed. Note that it is futile to try to test whether <ENTER> was pressed, because non-command keys also return 0 when pressed. At the start of the program, CMDKEY is initialized to -1.

See also FKey - a newer more powerful version of CMDKEY.

The CMDKEY function now accepts a value. This is useful for KSTAT$ processing and for setting expected CMDKEY inputs without operator intervention. In the following sample syntax, CMDKEY is assigned the value of x:

00010 LET CMDKEY(x)

CMDKEY now returns values of 90 and 91 for the PgUp and PgDn keys during program input. See "PgUp and PgDn" in the Keys section for more information.

Comments and Examples

09000 START: PRINT NEWPAGE
09010 PRINT "The record you tried to read is"
09020 PRINT "in use at another workstation."
09030 PRINT "*** Press F9 to try again, or"
09040 PRINT "*** <CR> to select another record"
09050 LINPUT DUMMY$
09060 IF CMDKEY = 9 THEN RETRY
09070 GOTO START

Line 9060 tests for the operator pressing the F9 key in response to the locked record message presented in the text above.

One more example:

00010 Start: print "Press a CMDKEY to see its value, or press 1 to quit"
00020 linput a$
00030 print CMDKEY
00040 if a$ <> "1" then goto Start

For other examples, see CURFLD

CMDKEY Values

FKey value Cause Additional
1 F1
2 F2
3 F3
4 F4
5 F5
6 F6
7 F7
8 F8
9 F9
10 F10
11 F11 or Shift+F1
12 F12 or Shift+F2
13 Shift+F3
14 Shift+F4
15 Shift+F5
16 Shift+F6 or Alt+Q
17 Shift+F7 or Alt+W
18 Shift+F8 or Alt+E
19 Shift+F9 or Alt+R
20 Shift+F10 or Alt+T
21 Ctrl+F1 or Alt+Y or SHIFT+F11
22 Ctrl+F2 or Alt+U or SHIFT+F12
23 Ctrl+F3 or Alt+I
24 Ctrl+F4 or Alt+O
25 Ctrl+F5 or Alt+P
26 Ctrl+F6
27 Ctrl+F7
28 Ctrl+F8
29 Ctrl+F9
30 Ctrl+F10 or Alt+A *
31 Ctrl+F11 or Alt+S *
32 Ctrl+F12 or Alt+D *
33 Alt+F *
34 Alt+G *
35 Alt+H *
36
37 Alt+K *
38 Alt+L *
39
40
41
44 Alt+Z *
45 Alt+X *
46 Alt+C *
47 Alt+V *
48 Alt+B *
49 Alt+N *
50 Alt+M *
90 page up
91 page down
92 tab change
93 Application Exit, Alt+F4 or Big X An Option exist to reassign this to a different value
98 Drop Down Menu ??
99 Escape or Alt+J *

Technical Considerations

  1. INPUT, LINPUT or RINPUT statements using the keyboard as input, or any INPUT FIELDS or INPUT SELECT statement will set the CmdKey variable.
  2. The Shift-F1 through Shift-F10 key combinations set CmdKey the values from 11 to 20.


CNT

CNT

See also the READ type for Grids

The CNT internal function returns the number of data items successfully processed by the last I/O statement. When there is an error in a field definition array in INPUT FIELDS, PRINT FIELDS or RINPUT FIELDS statements, CNT will return the number of the last successfully processed element in the error-causing field definition array.

Comments and Examples

When an I/O error occurs, the CNT function is very useful in debugging. Suppose the following program has two arrays of 52 elements each:

00510 READ #2,USING 520: MAT PAYTYPE$,FLAG$,MAT AMT
00520 FORM 52*C 1,N 1,52*N 5.2

Error code 0726 will occur on line 510 above to indicate a conversion error on one of the 103 items being read. As soon as the error occurs, the operator should enter PRINT CNT (or just CNT), and the system will print 52. This means the first 52 items were read successfully and the problem is in the 53rd item. CNT immediately localizes the problem to FLAG$ (which cannot be read with an N 1 format because it is a string variable).

In the following example, CNT is used within a program to redimension an array to the number of elements read:

00010 DIM A(20)
00020 DATA 1,2,3,4,5
00030 READ MAT A EOF 40
00040 MAT A(CNT)

Related Functions

The ERR and LINE functions are also commonly used for debugging.

Technical Considerations

If the current error was not an I/O error, CNT will be irrelevant because it contains information about a previous error.


CNVRT$

CNVRT$ (<spec$>, <numeric expression>)

The CNVRT$ internal function returns a string representing the numeric value X in the format specification coded in the string spec$. Spec$ is a string that has the same syntax as format specifications in the FORM statement for READ/WRITE operations. B, BH, BL, D, G, GZ, L, N, NZ, PD, PIC, S and ZD are allowed.

Comments and Examples

CNVRT$ is an enhanced version of STR$ that provides a lot of flexibility in converting a number to a string.

00010 LET A=0
00020 LET B=10
00030 LET C=.10
00040 PRINT USING 50: STR$(A),STR$(B),STR$(C)
00050 FORM C 5
00060 LET S$="NZ 5.2"
00070 PRINT USING 50: CNVRT$(S$,A), CNVRT$(S$,B), CNVRT$(S$,C)

The output on your screen would be:

    0  10 0.1
    10.00 0.10

Related Functions

The Str$ function also converts numbers to strings, but without the format control of CNVRT$.

Technical Considerations

  1. CNVRT$ takes much longer to execute than formatting with FORM statements.


CODE

CODE

The CODE internal function indicates the termination status of a program as set by the STOP or END statement. This completion code may be used in a procedure file with the SKIP command or it may be used in a subsequent program.

Comments and Examples

Suppose that a procedure normally runs two programs, but should not run the second program if there is a data entry error (e.g., invalid date) in the first program. The first program could set the CODE variable to a non- zero value if this type of error is detected. For example,

008050 IF YEAR < 1987 THEN STOP 1122

Line 8050 sets CODE to 1122.

The procedure that runs these two programs could test the value of CODE with a SKIP command as follows:

RUN PROGA
SKIP 1 IF CODE>0
RUN PROGB

Related Functions

ERR is often tested in procedures in a similar way.

Technical Considerations

When the system call (either Ctrl-] or the System command) starts and then exits a secondary software program before returning to BR, the Code function will reflect any return code that the secondary program has passed to the operating system. As soon as BR is reactivated, the value of CODE can be tested to Verify whether or not the secondary program was successful.

This feature is available on Unix / Linux versions of Business Rules! only.


COS

COS(<numeric expression>)

The COS(X) internal function is a trigonometric function that calculates the cosine of X in radians.

Example

00010 print COS(3.14)

Output:

-0.99999

Related Functions


CURCOL

CURCOL

The CURCOL internal function returns cursor column from the last INPUT FIELDS or RINPUT FIELDS statement.

CURROW and CURCOL return the row or column (within a window) of the first character position of the control being exited. However, if the control is a LIST or GRID then CURROW and CURCOL identify the cell that was exited relative to the control itself. (OPTION 59 provides the exact position of the mouse click.)

Comments and Examples

00100 DIM ALL$*1920
00110 INPUT FIELDS "1,1,c 1920,u": ALL$
00120 PRINT "Cursor ended on ROW"; CURROW
00130 PRINT "Cursor ended on COLUMN"; CURCOL
00140 PRINT "Cursor ended on FIELD"; CURFLD

In the sample program above, the entire screen is treated as one 1920-character input field. The operator can move the cursor to any of the 24 rows or any of the 80 columns. After the operator hits the <ENTER> key, line 120 will print the row number containing the cursor when input was ended. Also, line 130 will print the column number. Line 140 will print field 1 because there is only one large field in this example.

Related Functions


CURFLD

The CurFld internal function has 4 possible combinations of syntax:

CURFLD
 
CURFLD ([<New_current_field>] [,<attribute$>] [,FKEY])

CurFld ([<New_current_field>] [,<New_current_row>]) ! if the new current field is a ListView

CurFld ([<New_current_field>] [,<New_current_cell>])! if the new current field is a Grid

When used without parameters, CurFld function returns the number of the field containing the cursor from the last INPUT FIELDS. With parameters, CurFld can be used to set a new starting field (same as the C control attribute) and/or set a new attribute for the starting field. CurFld may also be used to set the cursor to a cell of a grid or a row in a ListView.

In other words, there are three uses for CURFLD:

  1. CURFLD, without parameters, returns the relative position of the last control (field) occupied during an INPUT operation.
  2. CURFLD(nn) returns the subscript of the current item within the 2D control (LIST or GRID) at relative position nn.
  3. CURFLD(nn,yy) positions the cursor at field yy in 2D control nn when the next INPUT operation is commenced. For LISTs, yy is a row value. For GRIDs it is a cell subscript value.

And, if the control being referenced by nn is not a 2D control, the following parameters are applied during the next INPUT operation-

  1. The relative field number.
  2. Optional additional field attributes.
  3. Optional FKEY value (e.g. right arrow) to be applied for cursor positioning before processing the INPUT.

Comments and Examples

00100 DIM SF$(3)
00110 LET SF$(1)="10,30,c 10,r"
00120 LET SF$(2)="12,30,c 10,r"
00130 LET SF$(3)="14,30,c 10,r"
00140 INPUT FIELDS MAT SF$: A$, B$, C$
00150 PRINT "Cursor ended on FIELD"; CURFLD
00160 PRINT "Cursor ended on ROW"; CURROW
00170 PRINT "Cursor ended on COLUMN"; CURCOL

In the sample program above, the there are three fields available for input. The operator can move the cursor in any direction, but only within these three fields. After the operator hits the <ENTER> key, line 150 will print the number 1, 2 or 3 depending on which field the operator left the cursor on. In addition, line 160 will print the row number (10, 12, or 14) containing the cursor when input was ended. Also, line 130 will print the column number (30 through 39).

Some programmers prefer to do screen input with only one field at a time. In these cases, CURFLD will always be 1 because only one field is used. CURFLD provides valuable information when several fields are entered in one statement through an array, specifically, when INPUT FIELDS, RINPUT FIELDS, INPUT SELECT, or RINPUT SELECT is used with an Array.

As CURFLD returns the subscript in the field definition array of the field containing the cursor from the last INPUT FIELDS, RINPUT FIELDS, INPUT SELECT, or RINPUT SELECT, CURFLD can be especially useful with the on-line help facility. By using CURFLD in the HELP$ function in line 990 for the value of the "mark", the operator can be directed to the most relevant portion of the text under the topic HOURS.ENTRY in the help file that explains the valid entries for that field. For example:

00810 INPUT FIELDS MAT FLD$: HRS,OT,DT,SICK HELP 90
00820 STOP
00990 HELP$("HOURS.ENTRY", CURFLD) : RETRY

The use of CURFLD with parameters is primarily designed for easy error processing. In the following example, CURFLD returns the cursor to the error-causing field and reverses the field for greater visibility. NOTE that this use of CURFLD takes affect only for execution of the next INPUT FIELDS, RINPUT FIELDS, INPUT SELECT, or RINPUT SELECT statement.

00010 INPUT FIELDS MAT A$: MAT A CONV 30
00020 IF A(2)>10 THEN LET CURFLD(2,"R") : GOTO 10
00030 STOP
00040 LET CURFLD("R")
00050 RETRY

FKEY Parameter

CurFld has been extended to allow an additional numeric parameter, an FKey value, that causes FIELDS and SELECT statements to execute the specified keystroke before requesting operator input. CURFLD ignores FKEY values of 100 or less and of 114 or greater. The following code uses CURFLD and FKEY to trap the operator's field exit keystroke and execute it after verifying the data just entered. NOTE that the AE control attributes are used to interrupt execution of the INPUT FIELDS statement upon field exit.

00010 PRINT NEWPAGE
00020 INPUT FIELDS "10,10,C 10,AEU:R;11,10,C10,U": X$,Y$ HELP 41
00030 IF CURFLD=1 THEN PRINT FIELDS "10,22,C": X$
00040 IF FKEY>100 THEN LET CURFLD(CURFLD,FKEY) : GOTO 20
00041 PRINT FKEY
00050 STOP

As soon as the operator attempts to exit the first input field, line 30 verifies the entered data by redisplaying it to the right of the field. The CURFLD function in line 40 is then used to reenact the operator's field exit operation: the field just verified is set to the current field, and the operator's attempted exit keystroke (the value of FKEY) is executed. Operator input is then allowed for the next field.

NOTE: If the up arrow was the last key used, the cursor will return to the previous field. If the tab key was used, the cursor will position to the next field with a T (tab stop) attribute.

NOTE that the CURFLD function in line 40 is executed only if the value of FKEY is greater than 100. Values of 100 or less are ignored, as they are interpreted as an attempt to enter the entire screen.

CURFLD will now process field control attributes such as AEP and #. These control attributes will be ADDED to the control attributes that are specified for a field. Also, the attributes that are specified with CURFLD will OVERRIDE (be used instead of) a floating attribute specified with ATTR. The CURFLD attributes will remain in effect only during the next execution of an INPUT FIELDS or INPUT SELECT statement. Line 20 in the following example uses the X control attribute (see the "X control attribute" discussion in the BRConfig.sys Specifications section for more information).

00010 INPUT FIELDS "10,10,V 10,U;11,10,V 10,U;12,10,V 10,U",attr "HU":X$,Y$,Z$
00020 IF X$="" THEN LET CURFLD(1,"RX") : GOTO 10
00030 !.. other editing
00040 IF FKEY>100 THEN LET CURFLD(CURFLD,FKEY) : GOTO 10
00050 !.. output

If the first field displayed by the above code is left blank, the CURFLD function in line 20 will reposition the cursor to that field and display it in reverse video. The CURFLD function's X attribute will additionally cause an auto-enter to occur when the operator attempts to re-exit the field. If the field passes the test on line 20, and the enter key or a function key was not pressed, the field attribute will resume as an underline and the cursor will be positioned at the next field the operator was trying to move to.

BRC expects that line 40 will become a standard line of code in all programs that use input fields and validate data.

Previously, the CurFld statement supported 3 parameters:

  1. The relative field number.
  2. Optional additional field attributes.
  3. An optional FKEY value to be applied for cursor positioning before processing the INPUT.

In the event the first parameter points to a 2D field/control then instead of the FKEY value, the third (or second numeric) parameter is interpreted as the subscript of the item within the 2D control. For LISTs, this is a row value. For GRIDs this is a Cell Subscript Value. For TOOLBARs, it is the icon subscript value (relative position in toolbar).

Also, in the event the first parameter points to a 2D field/control then the CURFLD function returns the subscript of the current item within the 2D control.

The CURFLD system function has been extended to support the current selection upon entry to a multi-field control. The first parameter specifies which field/control is to be affected and the second parameter is the subscript of the cursor upon entry to that control. In the event the first parameter points to a 2D field/control then instead of the FKEY value, the third (or second numeric) parameter is interpreted as the subscript of the item within the 2D control.

|For LISTviews this is a row value.
|For GRIDs this is a Cell Subscript Value.
|For TOOLBARs it is the icon subscript value (relative position in toolbar).
Note that CURFLD with 2 parameters does not set the initial position of the cursor until the respective control is entered. Also if the mouse is used to enter a control, that will override the specified CURFLD value.

Option 43 Use old style Input Select with respect to setting CURFLD to the NXTFLD value when a selection is made.

Technical Considerations

Note that before BR 4.2, CURFLD could be used with RINPUT FIELDS, INPUT SELECT, or RINPUT SELECT. But as of 4.2, it is limited to INPUT FIELDS.

CurFld is initialized to -1 at the start of a new program by the RUN command.

Related Functions

CURROW and CURCOL return the row and column numbers of the last INPUT FIELDS, RINPUT FIELDS, INPUT SELECT, or RINPUT SELECT statement.


CURROW

CURROW

The CURROW internal function returns the cursor's row from last Input Fields or RInput Fields statement.

CURROW and CURCOL return the row or column (within a window) of the first character position of the control being exited. However, if the control is a LIST or GRID then CURROW and CURCOL identify the cell that was exited relative to the control itself (see Grid and List). (OPTION 59 provides the exact position of the mouse click.)

Comments and Examples

00100 DIM ALL$*1920
00110 INPUT FIELDS "1,1,c 1920,u": ALL$
00120 PRINT "Cursor ended on ROW"; CURROW
00130 PRINT "Cursor ended on COLUMN"; CURCOL
00140 PRINT "Cursor ended on FIELD"; CURFLD

In the sample program above, the entire screen is treated as one 1920-character input field. The operator can move the cursor to any of the 24 rows or any of the 80 columns. After the operator hits the <ENTER> key, line 120 will print the row number containing the cursor when input was ended. Also, line 130 will print the column number. Line 140 will print field 1 because there is only one large field in this example.

Related Functions


CURWINDOW

CURWINDOW(<window-number>) 

The CURWINDOW internal function identifies the number of the window currently in focus if this window was open with the PARENT=NONE option. If a window number is given, then that window is given focus (raised).

This is helpful when working with parent=none windows and F93.

Related Functions


DATE

See also Date (disambiguation)

DATE([<DAYS>], [*<order_of_components$>])

The Date internal function calculates and returns dates in numeric format, using no dashes or slashes as separators. Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point), as of 4.3.

The optional "days" parameter represents the desired date as a sequential value in relation to a base date of January 1, 1900. Thus January 1, 1900 would have a days value of 1; January 1, 1901 would have a days value of 366 (1900 was not a leap year).

When order_of_components$ is specified, the date is printed accordingly. order_of_components$ may be any combination of the four letter M (month, D (day), C (century), Y (year). Including each of these components results in a two-digit corresponding month, day, century, or year. When any of these 4 components is omitted, it is not returned by the function or printed.

If the order_of_components$ parameter begins with an asterisk (*), then the default format is changed. The default format affects results of the Date, Date$ and Days functions. This change applies only to the current computer and stays in effect until you exit BR.

DATE can also be used as an INPUT FIELDS specification as of 4.3.

Examples

Executing the following statement on July 10, 1992

PRINT DATE("MDCY")

results in the following output:

7101992

Note that BR does not print the zero in front of the month July (07), as this is not necessary for numeric calculations. If you do not need the numeric value of the date, use the Date$ function instead.

Consider another example, in which 33794 is the number of days which passed between January 1, 1900 and July 10, 1992:

PRINT DATE(33794,"MDY")

with the following output:

71092

The DATE function should not be confused with the DATE command, which may be used to reset or display the current system date.

Comments and Examples

00010 PRINT FIELDS "10,10,CR 20": "Enter Posting Date:"
00020 PRINT FIELDS "10,43,N 6,r": DATE("mdy")
00030 INPUT FIELDS "10,43,N 6,r3": POSTDATE

Line 20 displays the current system date as a number in the format month, day and year. Line 30 positions the cursor to the third digit and allows the operator the option to change the displayed date by typing over all or part of it.

Technical Considerations

The DATE function cannot be used in READY mode unless it includes parameters. If you type in "DATE" and press <ENTER>, you will be using the DATE command, which uses a different default format than the DATE function does.

Use with Input Fields

DATE(mask) can be used as an INPUT FIELDS specification as of 4.3.

10 INPUT FIELDS “row, col, DATE(mask),UH” : date-variable

Special keyboard processing:

  • Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry, similar to PIC.
  • Insert and delete are supported within subfields that are delineated by punctuation.
  • Copy includes punctuation.
  • Cut is Copy with redisplay of zero date.
  • Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.
  • If a string is pasted, it is first converted to DAYS using the provided mask.
  • If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.

Date Picker

A date picker is available.

This configuration statement controls when the date picker appears:

DATE [ALWAYS]|[INVALID]|[NEVER]

ALWAYS show the picker whenever the cursor is in the field until a date is selected from the picker. Leaving the field and reentering it actives the picker again. Additionally, the optional leading attribute ^DATE_PICKER will do the same thing.

INVALID (the default) presents the date picker whenever the days value of the expressed date is zero.

NEVER will make the Date Picker never appear.

Also, the Date Picker appears when the cursor is in a DATE field and the user presses Ctrl-DownArrow (Note-the same key combination will open a Combo Box ).

Additionally, when in the date picker INPUT FIELDS, the following keys are active:

  • Shift- PgUp/PgDn – Go to the previous/next month
  • Ctrl- PgUp/PgDn – Go to the previous/next year


Sample Program

A sample program to demonstrate date entry is:

01000 ! Rep Date_Input
01020 ! Demonstrate The New Date() Input Format
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation
01080 ! Continue To Support Cut And Paste Including Punctuation
01100 ! 
01120    rinput fields "5,10,DATE(mm/dd/yy) ;6,10,c": DATE_VAR
01140    print fields "8,10,date(Month DD, CCYY)": DATE_VAR
01160 ! 
01180    rinput fields "12,10,date(month dd, ccyy)": DATE_VAR
01200    if NOT DATE_VAR then goto 1180
01220    print fields "15,10,date(yy/mm/dd)": DATE_VAR 
01240    print fields "18,10,N 6": DATE_VAR  !Show days format


Related Functions

See also Date$ and Days for other date processing functions. To set the system date, use the Date command. For features especially useful in markets outside the United States, see the INVP parameter of the Option statement and the PIC$ function in the Format Specifications.


DATE$

Date$
Date$(<days>)
Date$([*]<format$>)
Date$(<days>,[*]<format$>)

The Date$ internal function returns the date as a formatted string which includes optional punctuation marks as separators between the month, day, and year. DATE$() works with day-of-century values along with an optional time fraction (use of fractions, 4.3+).

Comments and Examples

The four examples below all change the date format temporarily so that the month will print before the day of the month, which will print before the year. For a system date of December 25, 1988, the printed output is given as a comment at the end of the line for each example.

00010 PRINT DATE$("mm-dd-yy")    ! 12-25-88
00020 PRINT DATE$("m.d.y")       ! 12.25.88
00030 PRINT DATE$("DD/MM/YY")    ! 25/12/88
00040 PRINT DATE$("MMDDYY")      ! 122588
00050 PRINT DATE$                ! 88/12/25

NOTICE in line 50 that the output automatically returns to the default format. When BR is started, the default format is yy/mm/dd. Other possible uses of Date$ include returning only the day, month, year or century.

00050 PRINT DATE$("m")           ! 12
00060 PRINT DATE$("D")           ! 25
00070 PRINT DATE$("y")           ! 88
00080 PRINT DATE$("m-d-cy")      ! 12-25-1988
00090 PRINT DATE$("C")           ! 19

The optional numeric parameter (days) allows specifying a day of the century. The following example assumes the system date is Christmas, 1988.

00010 PRINT DATE$("*mm-dd-ccyy") ! 12-25-1988
00020 PRINT DATE$(1)             ! 01-02-1900
00030 PRINT DATE$(366)           ! 01-01-1901
00040 PRINT DATE$(Days(DATE))    ! 12-25-1988
00050 PRINT DATE$(Days(DATE)+10) ! 01-04-1989

Lines 10 and 20 above could be combined into line 500 below.

00500 PRINT DATE$(1,"*mm-dd-ccyy") ! 01-02-1900

As the above specification includes the asterisk, the default format for all future uses of the Date, Date$ and Days functions is changed to mm-dd-ccyy, as specified.

The following is a short program that will center "July 4, 1988" (or any other value set by the Date command) at the top of a report. Note that this example is for illustrative purposes only, because the extended formats below eliminate the need for this code snippet.

00010 DIM MONTH$(12)*9
00020 READ MAT MONTH$
00030 DATA "January ","February ","March ","April ","May "
00040 DATA "June ","July ","August ","September ","October "
00050 DATA "November ","December "
00060 PRINT #255,USING 70: MONTH$(DATE("m")) & DATE$("d, cy")
00070 FORM CC 132

Extended Date Formats That May Include Time of Day

DATE$(days, "day month, ccyy") -> 23 January, 2007
DATE$(days, "d3 m3 dd, ccyy") -> Tue Jan 10, 2005
DAYS("January 17, 1945", "month dd, ccyy") -> 16435 (numeric days)

DATE$( days, “Month dd, ccyy at H#.##”) -> September 12, 2011 at 14.58 hours
DATE$( days, “mm/dd/yy at H:M AM”) -> 09/15/11 at 2:35 PM
DATE$( days, “mon dd cy at H#:M# PM”) -> Sep 15 2011 at 02:35 PM

Parameter Rules

When the Date$ function is used without parameters, it returns the current system date in the current default format, which is yy/mm/dd when Business Rules is started.

The optional "days" parameter represents the desired date as a sequential value in relation to a base date of January 1, 1900. Thus January 2, 1900 would have a days value of 1. January 2, 1901 would have a days value of 366, since 1900 was not a leap year.

The optional "format$" parameter is a string expression which identifies the format of the value to be returned. When the first character of the string expression is an asterisk (*), it identifies the default format which should be used by the Date, Date$ and Days parameters until the computer exits Business Rules or until the format is changed again. Format changes affect the current computer only.

The format$ parameter may include editing characters and any of the following date specifications: D (day), M (month), Y (year) or C (century). Consecutive repetitions (DDD, YY, etc.) of the date specifications count as just one specification, but consecutive repetitions of other editing characters do not use this rule.

The following rules apply to the format$ parameter for the Date$, Date and Days functions:

  1. The D, M, Y and C specifications may be specified in either uppercase or lowercase letters.
  2. Consecutive repetitions of the D, M, Y or C specifications count as just one specification. Thus DDDD is one specification, and cc is one specification.
  3. All characters other than D, M, Y or C are considered editing characters, and are ignored for the numeric Date function.
  4. If the string parameter begins with an asterisk (*), then the default format is changed. The default format affects results of the Date, Date$ and Days functions. This change applies only to the current workstation and stays in effect until you leave Business Rules.

And as of 4.3:

  1. M, to the right of H always denotes minutes, so H:M:S is sufficient.
  2. Either AM or PM, to the right of H denotes AM / PM output.
  3. The absence of AM and PM denote military hours (0 – 23).
  4. The maximum significant digits that can be represented in a numeric variable are 15. So if century, year, month and day are stored as a 5 digit day of century, then internally up to ten digits to the right of the decimal are available for time of day.

Related Functions

See also Date and Days for other date processing functions. To set the system date, use the Date (Command). For other features especially useful in markets outside the United States, see the INVP parameter of the Option statement and the Pic$ function

Saving Dates

When storing date/time combinations in a data file, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 4.4” form supports nine significant digits, which is suitable for day of century plus a four digit fraction. To exceed that you can use either PD 6.6, PD 7.6, PD 8.6 or D 8 (double floating point) to store these values. Note that BR rounds internally at six digits by default.


DAYS

DAYS (<date>[,<format$>])

DAYS internal function returns the absolute, sequential value which is assigned to dates after January 1, 1900.

BaseYear is used to determine the century for a date if the format specification used does not specify a century. See BaseYear in the BRConfig.sys specifications section for complete information.

Comments and Examples

The Days function returns the specified date as a sequential value in relation to a base date of January 1, 1900. As an example of using this parameter for date arithmetic, line 300 would print "PAST DUE" if the date of an invoice IDATE is over 30 days from the current date.

00030 IF Days(DATE)>Days(IDATE)+30 THEN PRINT "Past Due"

The DAYS function can now be used to store and perform date arithmetic on dates beginning with year 1700. Negative numbers are used to denote such dates.

Notice that the number of days in a month, leap year, etc. do not have to be coded in your program because they are built into this function.

If the numeric date parameter is invalid, the Days function will return zero. Therefore, the Days function can also be used to check the validity of dates entered from the keyboard. For example,

00010 LET DATE$("*y/m/d") ! be sure default format is year/month/day
00020 LET M$="14"         ! month is invalid
00030 LET D$="31"
00040 LET Y$="88"
00050 LET D=VAL(Y$&M$&D$) ! D = 881431
00060 PRINT Days(D)       ! invalid date = 0
00070 LET M$="12"         ! month is valid
00080 LET D=VAL(Y$&M$&D$) ! D = 881231
00090 PRINT Days(D)       ! valid date = 32507
00095 LET DATE$("*m/d/y") ! change default format to month/day/year
00096 PRINT Days(D)       ! invalid date = 0 (does not fit format)

The value of D in line 96 is invalid because line 95 changes the default format for dates (note the * at the start of the date string). The optional second parameter of the Days function can be used to temporarily change the date format. Line 97 will print a nonzero value because the date is valid in the format specified in the optional string parameter.

00097 PRINT Days(D,"y/m/d") ! valid date = 32507
00098 PRINT Days(D)         ! invalid date = 0 (does not fit format specified  in line 95)

Line 98 returns zero because the format in line 97 only applies to that one function call. Since there is no asterisk in the date string, line 97 does not change the default date format, whereas line 95 does.

Parameters

The "date" parameter is a numeric expression that represents the date for which the number of days should be calculated. If "date" is not valid according to the current default format, Days will return 0.

The optional "format$" parameter is a string expression which identifies the format of the value to be returned. When the first character of the string expression includes an asterisk (*), it identifies the default format which should be used by the Date, Date$ and Days parameters until the workstation exits Business Rules or until the format is changed again. Format changes affect the current workstation only.

The format$ parameter may include separating characters and any of the following date specifications: D (day), M (month), Y (year) or C (century). The total number of separating characters and date specifications may not exceed 6. Consecutive repetitions (DDD, YY, etc.) of the date specifications count as just one specification, but consecutive repetitions of separating characters do not use this rule. See the Date$ function for additional information about format$.

Handling Input

(4.2+) BR does not require that the entered value conform to the specified mask to avoid the entry of incorrect dates using unforeseen valid expressions. If a date format mask omits month, day, year and/or century, BR assumes the first day of the current month for the respective omitted mask components. Values must conform to masks with the following exceptions:

  • Any valid format for month or day is accepted on input where the mask requests the respective month or day.
  • Any valid separator will be accepted where any separator is specified by the mask.

Otherwise, BR requires that the entered value conform to the specified mask to avoid the entry of incorrect dates using unforeseen valid expressions.

Examples:

  days("Tuesday 23 January, 2007",'day dd month, ccyy') -> 39104
  days("January, 2007",'day dd month, ccyy') -> 39082  (day 1 assumed)
  days("Tuesday 23 Jan; 07",'day dd m3, yy') -> 39104  (note mm yy separator)
  days("Tuesday 23 Jan/ 07",'day dd m3, yy') -> 39104
  days("Tuesday 23 Jan; 07",'day dd m3, yy') -> 39104
  days("Tuesday 23 Jan- 07",'day dd m3, yy') -> 39104
  days("23 Jan;",'dd m3,')                   -> 40200  (current year and century)

BR allows a null mask, but the omission of a mask does not denote a null mask. It denotes whatever the system default mask is currently set to, which could be the system default.

  • As of 4.3, numeric variables can now represent time of day in the fractional space (to the right of the decimal point) to include the following:
  H#.## or H denotes hours (with fractions).
  M#.### or M#.# denotes minutes.
  S#.####, S or S# denotes seconds.

M, to the right of H always denotes minutes, so H:M:S is sufficient. Either AM or PM, to the right of H denotes AM / PM output. The absence of AM and PM denote military hours (0 – 23). The maximum significant digits that can be represented in a numeric variable are 15. So if century, year, month and day are stored as a 5 digit day of century, then internally up to ten digits to the right of the decimal are available for time of day.

Examples:

  DAYS("7/13/15 03:10:57 AM","M/D/Y H:M:S AM")     -> 42197.1326042
  DAYS("03:10:57 AM","H:M:S AM")                   -> 42185.1326042   
  DAYS("7/13/15 03.1825","M/D/Y H#.####")       -> 42197.1326042

Notes:

  • When using H:M:S, the time Component must be HH:MM:SS, so for example 3:10:57 PM will not work properly
  • When providing a time without a date, the function will return the days value for the 1st day of THIS month. In the Above examples, the date was 7/13/15
  • When using H#.#### the Hours must be 2 Digits "03" not "3", and the # of decimals must at least match the mask provided.

Saving Dates

When storing date/time combinations in a data file, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 4.4” form supports nine significant digits, which is suitable for day of century plus a four digit fraction. To exceed that you can use either PD 6.6, PD 7.6, PD 8.6 or D 8 (double floating point) to store these values. Note that BR rounds internally at six digits by default.

Related Functions

See also Date$ and Date for other date processing functions.


DEBUG_STR

Debug_Str(<message-level>, <string-value>)

The Debug_Str internal function will, depending on loglevel (message-level must be equal or lower), send data to the logfile as well as to the debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON.

Any DEBUG_STR() calls with a message-level greater than 10 are deemed to be message-level 10.

This function is available as of BR! 4.3


DIDX

DIDX (<array name>)

The DIDX internal function returns an array that is a descending index obtained from sorting the array named. The array to be sorted may be either string or numeric. Only permitted in the MAT statement.

Note that you cannot use the Mat keyword in the array name parameter of this function.

Correct:

00010 MAT DescendingIndexArray(UDIM(ArrayToBeIndexed$))=AIDX(ArrayToBeIndexed$)

Incorrect:

00010 MAT DescendingIndexArray(UDIM(ArrayToBeIndexed$))=AIDX(MAT ArrayToBeIndexed$)

Comments and Examples

The program below will sort and print an array of names in reverse alphabetical order:

00100 DIM A(100),N$(100)
00110 DATA "Tom", "Colleen", "Bill", "Christi"
00120 DATA "Tim", "Dave", "Sheila", "Jenni"
00130 DATA "Pam", "Laura", "Jean", "Michele"
00140 DATA "Gary", "Gordon", "Mallika"
00150 READ MAT N$ EOF 155
00155 MAT N$(CNT)
00160 MAT A(UDIM(N$))=DIDX(N$) ! 
00170 FOR I=1 TO 15
00180    PRINT N$(A(I))
00190 NEXT I

Related Functions

Other functions that operate on arrays are

Technical Considerations

  1. DIdx will places equal array elements into ascending order by array index. In other words, for an array with three elements 10, 20 and 20, DIdx will return 2, 3, 1 (instead of 3, 2, 1).
  2. The RD specification in BRConfig.sys can affect the DIdx function because it determines when two numeric values are considered equal.
  3. The COLLATE option in effect when the program was last saved or in the OPTION statement can alter the sort order from the DIDX function when sorting string values.
  4. To use DIDX, the arrays on both sides of the equal sign must have the same dimensions.


ENV$

ENV$(<variable>)

The Env$(var$) returns the current value of the specified environment variable. To see a list of operating system environmental variables, enter the SET command with no parameters at the operating system prompt.

BR internal environmental values can be set by CONFIG SETENV. For example, use the following command to set the value of env$("librarypath"):

config setenv librarypath f:\apps\library\

Operating system ENV$ variables cannot be set or altered by CONFIG SETENV.

The Env$ function is used to retrieve local BR only environmental variable values (which were set with SetEnv).

Example:

got1$=env$("UserName")
got2$=env$("GUIMode")

Comments and Examples

As an example, if LOGNAME contains the login name, the following line in a menu program would require a user to log in as "root" to be able to run program PROG14.

00040 if env$("LogName")="root" then chain "Prog14" else goto SHOWMENU

For a complete list of possible ENV$ arguments issue the following command:

Status Env [ -P ]

Example:

ENV$("SERVER_PLATFORM")      

Returns “WINDOWS”

Technical Considerations

  1. Linux and MAC versions of Business Rules require that user-created environment variables be passed by an export command to the operating system before the user enters Business Rules. This is a normal Linux/ MAC OS X requirement. Otherwise, the values of these variables are not accessible to BR.
  2. There is a BR provided Env$ variable called GUIMODE (case insensitive). It's value is either ON or OFF depending on whether BR is in GUI mode.
  3. The keyword CLIPBOARD retrieves the current contents of the Windows clipboard.
  4. BR_MODEL returns the model of Business Rules currently operating (COMBINED or CLIENT/SERVER).
  5. Also see Monitor Interrogation below.

BR SETTINGS ENVIRONMENT COMPREHENSIVE INTERROGATION

The ENV$("STATUS") function can be used to retrieve a broad range of program environment data. It returns the same type of data that the STATUS ENV command returns, except:

  1. It populates a string array with the data.
  2. ENV$("status" ... returns only the values of environment variables, whereas ST ENV shows each whole ENV$() expression along with its corresponding value.


ENV$("STATUS [ .sub-keyword ] ... " [, mat config$ ] [, "search-arg , ... " ] )

ENV$ returns a string, or in the event that a string array (e.g. MAT CONFIG$) is specified, ENV$ redimensions and loads the array with the associated values.

Use STATUS sub-keywords to restrict the output to exact terms. For a list of valid keywords issue a STATUS ENV "status" -P command. The subtle aspect of this is that STATUS ENV shows all environment variables accessible via ENV$, whereas only the ENV$("status") values can be sent to an array.

Note that, while sub-keywords are case insensitive, they must be spelled out in their entirety. e.g. ENV$('status.attribute') fails to produce any results, whereas ENV$('status.attributes') produces many results. [To see a list of attributes currently in effect enter ST ATTR at the keyboard. Or enter ST ENV 'attr' for ENV$ values of specific attributes.] This complete spelling requirement is meant for programs (as distinguished with command line inquiry), and avoids inadvertent argument matching. However, ad-hoc inquiry is facilitated by optional additional case insensitive string filter arguments.

Like the STATUS ENV command, ad hoc comma separated search arguments in a single quoted string may be specified to filter the output. Each search argument provided is matched (case insensitive) against each output line and only matching lines are output. Individual comma separated search words may be preceded with a tilde (~) to indicate exclusion of matching lines. Each argument is space trimmed before comparing.

It is not necessary to provide an array to receive the results. If only one value is needed and no array is provided, the first value produced by the ENV$ call is returned as the string value of the function, and the search argument(s) can conveniently narrow the result to the desired term.

The following program displays all STATUS information that contains the word “file”:

00100    dim CONFIG$(1)*100
00120    let ENV$("STATUS",MAT CONFIG$,"file")
00140    print MAT CONFIG$

The above program produces the following output:

CHAINDFLT   - Look for object files with source first.
EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE
FILENAMES LOWER_CASE
OPTION 23 is OFF - prevent data conversion errors from moving file position
OPTION 25 is ON - make FILE$(0) be CON: if in windows
OPTION 26 is OFF - suppress creation of .BAK files
OPTION 29 is ON - save programs as .WB files
OPTION 33 is 64 - locking position for large file support
OPTION 49 is OFF - use relative path for spool file
OPTION 51 is OFF - recover deleted records for all files
SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]
Server File: :c:\wbserver.dat
BR Config File: :C:\ADS\SYS\br.d\brconfig.sys
Executable File: :C:\ADS\SYS\br.d\ 
brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe
Serial File: :C:\ADS\SYS\br.d\brserial.dat
Workfile path: :c:\ads
Open File #  0  :CON:

If you just want the options with the word file then use:

00100    dim CONFIG$(1)*100
00120    let ENV$("STATUS.CONFIG.OPTION",MAT CONFIG$,"file")
00140    print MAT CONFIG$

This uses both the sub-keywords and the search string to filter the output which produces:

OPTION 23 is OFF - prevent data conversion errors from moving file position
OPTION 25 is ON - make FILE$(0) be CON: if in windows
OPTION 26 is OFF - suppress creation of .BAK files
OPTION 29 is ON - save programs as .WB files
OPTION 33 is 64 - locking position for large file support
OPTION 49 is OFF - use relative path for spool file
OPTION 51 is OFF - recover deleted records for all files 

Note that while sub-keywords are case insensitive, they must be completely specified, whereas search strings are more “friendly”. For a complete list of valid keywords, issue the command:

STATUS ENV -p

Some of the keywords supported are:

ENV$("CLIENT_PLATFORM") is "WINDOWS"
ENV$("CLIENT_PLATFORM.BR_BUILD_TYPE") is "DebugEfence"
ENV$("CLIENT_PLATFORM.BR_BUILD_DATE") is "2011-05-12"
ENV$("CLIENT_PLATFORM.BR_BITS") is "32"
ENV$("CLIENT_PLATFORM.OS_BITS") is "64"
ENV$("CLIENT_PLATFORM.OS_VERSION_NAME") is "Windows 7"
ENV$("CLIENT_PLATFORM.OS_VERSION_NUMBER") is "6.1"
ENV$("SERVER_PLATFORM") is "LINUX"
ENV$("SERVER_PLATFORM.BR_BUILD_TYPE") is "DebugEfence"
ENV$("SERVER_PLATFORM.BR_BUILD_DATE") is "2011-05-13"
ENV$("SERVER_PLATFORM.BR_BITS") is "64"
ENV$("SERVER_PLATFORM.OS_BITS") is ""
ENV$("SERVER_PLATFORM.OS_VERSION_NAME") is "#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010"
ENV$("SERVER_PLATFORM.OS_VERSION_NUMBER") is "2.6.32-22-server"	
BR_MODEL		  “CLIENT/SERVER” or “COMBINED”

Monitor Configuration Interrogation

ENV$("MONITOR1 | MONITOR2", MAT <num-arrayname>)

Either MONITOR1 or MONITOR2 redimensions num-arrayname to 4 elements and returns X (horizontal) and Y (vertical), of the upper left corner, and Width and Height in pixels ofthe current setting for either monitor 1 or monitor 2. Monitor 2 can be regarded as an extension of monitor 1 concerning the total video space.

Example Program (cut and paste into a text editor – then LOAD file SOURCE):

00010    let MONITORS$ = ENV$("monitor_count")
00020    let MONITORS = VAL(MONITORS$)
00030    print MONITORS
00040    for I = 1 to MONITORS
00050       let ENV$("monitor"&STR$(I), MAT TEST)
00060       for J = 1 to 4
00070          print TEST(J);
00080       next J
00090       print 
00100    next I

Results for 2 monitors of differing sizes:

2
0 0 1280 1024 
1280 0 1024 768


Accessing the Client's Environment when in Client Server

EXECUTE '*sys -M set >Workfile-[session].txt

This is really a workaround as BR does not grant direct access to the CLIENT environment variables.

A Recomendation is to add a "Prefix" to each of the clients environment, as an example "CS_".

A Few examples that might be of interest

  • CS_USERNAME = The actual user logged on to the workstation
  • CS_COMPUTERNAME = The actual computername of the workstaiton.
  • CS_TEMP = The actual %TEMP% folder for the workstation.



The following is a "Snipet" of code that reads the client environment.

    • NOTE: The following code won't work on it's own **
 39032   DIM Cs_Worked$*512,Tempenv$*2048,Addstr$*3, Leftstr$*2048, Rightstr$*2048
 39035   LET Cs_Worked$='Failed Execute of: *sys -M set > "'&Cs_Textfile_Make$&'"'
 39040   EXECUTE '*sys -M set > "'&Cs_Textfile_Make$&'"' ERROR XIT_FNCS_ENV
 39045   LET Cs_Worked$='Failed to Open: '&Cs_Textfile_Open$
 39050   OPEN #1: 'NAME='&Cs_Textfile_Open$,DISPLAY,INPUT ERROR XIT_FNCS_ENV
 39055   LET Cs_Worked$=""
 39060 STARTLOOP: ! 
 39070   LET Addstr$="CS_"
 39080   DO 
 39090     LINPUT #1: Tempenv$ ERROR XIT_LOOP
 39100     LET Gw_Wholeline=Len(Rtrm$(Tempenv$)) !:
           LET Gw_Addlen=1 !:
           LET Gw_Posfnwp=Pos(Uprc$(Tempenv$),"=")
 39110     IF Gw_Posfnwp>0 THEN 
 39120       LET Gw_Equal =Pos(Tempenv$,'=')
 39130       LET Gw_Nextequal =Pos(Tempenv$,'=',Gw_Posfnwp+Gw_Addlen)
 39140       IF Gw_Equal > 0 THEN 
 39150         LET Leftstr$ = Addstr$&Tempenv$(1:Gw_Posfnwp-1)
 39160         LET Rightstr$ = Tempenv$(Gw_Posfnwp+1:Gw_Wholeline)
 39170         LET Setenv(Leftstr$,Rightstr$) ERROR 39180
 39180 ! Should SETENV FAIL, Ignore it
 39190       END IF 
 39200     END IF 
 39210   LOOP 
 39220 XIT_LOOP: ! End of Startloop
 39230   CLOSE #1: ERROR 39240
 39240 ! 
 39260 XIT_FNCS_ENV: !

ERR

ERR

The Err internal function returns the error code of the most recent error.

Comments and Examples

Program errors which are not anticipated can be handled by adding the following to any program.

00001 ON ERROR GOTO 99900
   o
   o
99900 PRINT "Unexpected Error Number";ERR
99910 PRINT "occurred at line number";LINE
99920 PRINT
99930 PRINT "Please record this information,"
99940 PRINT "and call your dealer at once!"
99950 PAUSE
99960 CHAIN "MENU"

ERR is also used in procedures to determine when commands are successful. In the following procedure, a PROTECT command is used to reserve a file on a multi-user system before attempting to rebuild the index for the file.

PROCERR RETURN
PROTECT CUSTOMER,RESERVE
PROCERR STOP
SKIP DONE IF ERR<>0
INDEX CUSTOMER CUSTOMER.KEY 1 4 REPLACE
:DONE
CHAIN "menu"

PROCERR RETURN does two important things in this procedure. It turns off normal system error processing so that the system will not stop or beep if an error occurs. Also, it resets ERR to zero. After PROCERR STOP reinstates normal error processing, the SKIP command checks ERR and branches to the label DONE if ERR is no longer zero.

Related Functions

Technical Considerations

  1. ERR is initialized to zero by the following: the RUN command, PROCERR RETURN command, CLEAR or CLEAR ALL commands and any other commands which clear memory.
  2. There are three cases where errors occur and ERR is not set. First, ERR is not changed when an ON error statement (or default) has set to IGNORE the error condition corresponding to this error. Second, when the error code is 4273 (topic not found in help file), the system does not set ERR or LINE so that an error in attempting to use the HELP$ function in an error trapping routine will not affect the ability to use RETRY or CONTINUE. Third, the value of ERR is not affected when an error occurs in an immediate statement which has been keyed in from the keyboard; the error code for this immediate statement is displayed correctly in the status line.
  3. Even when PROCERR RETURN is used in a procedure file to skip an error, the value of ERR is still set and can be tested with a SKIP command, such as SKIP 3 IF ERR=0
  4. ERR is affected by any error-causing string expression which is executed by a line-numbered EXECUTE statement.


EXISTS

Exists(<filename>)

The exists internal function returns a nonzero value if the specified file (PROC or program)exists and the user has read privileges. If one or both of these conditions is false, exists returns a value of zero. NOTE that on single-user systems, all files have read privileges for the current user.

The exists function returns:

  • a value of 1 for directories
  • a number greater than 1 for files

Comments and Examples

Future
Future releases of Business Rules! may return the file type (e.g., 4 for internal, 9/10/11 for programs).



For the present, do not test for any specific positive value. Only zero or non-zero tests should be used. Recommended coding practices for programs are:

00010 IF EXISTS("filename") THEN GOTO FOUND
00020 IF EXISTS("filename") <> 0 THEN GOTO FOUND
00030 IF NOT EXISTS("filename") THEN GOTO NOTFOUND
00040 IF EXISTS("filename") = 0 THEN GOTO NOTFOUND

Recommended coding practices for procedures

SKIP FOUND IF EXISTS(filename)
SKIP FOUND IF EXISTS(filename) <> 0
SKIP NOTFOUND IF NOT EXISTS(filename)
SKIP NOTFOUND IF EXISTS(filename) = 0

Related Functions

For additional information about files, see the following functions:

Technical Considerations

  1. Due to anticipated enhancements for this function, it is strongly recommended that you use only zero or nonzero tests in your code. Do not attempt to test for a specific nonzero value.


EXP

Exp(<numeric expression>)

The Exp internal function calculates the exponential value of X. The mathematical number e, which is approximately equal to 2.718, is raised to the power X. The example below

00010 print exp(2)

results in

7.389056

Related Functions:


FILE

File(<file handle>)

The File internal function returns the numeric value that specifies the status of file associated with the File Handle.

-1 File not opened.
0 Operation performed successfully.
10 End of file occurred during input.
11 End of file occurred during output.
20 Transmission error during input.
21 Transmission error during output.

Comments and Examples

Print File(N) will return -1 when the file N is not opened. File(N) can be used to separate input from output errors in file processing, including communications files.

Window Interrogation

Using file with the optional parameters, WINDOW_RECT or USABLE_RECT allows BR to distinguish between window dimensions and the useable area of windows.

file(nn,"WINDOW_RECT | USABLE_RECT", MAT num-arrayname)

The above file() reference redimensions num-arrayname to 4 elements and returns X (horizontal), Y (vertical), Width, and Height in pixels of either the window or usable area rectangle.

Fontsize

Using File with FONTSIZE returns a two element array with the height and width of each fixed character position in pixels (used for positioning and sizing controls). For example:

file(N,"FONTSIZE", MAT num-arrayname)


extended syntax examples
file(101,'WINDOW_RECT',mat x)

returns 4 items in mat x

  • x(1)=left
  • x(2)=top
  • x(3)=width
  • x(4)=height


See Also

For additional information about files, see the following:


FILE$

File$(<file name>)

The File$(N) internal function returns the path and name of file N. When used without parameters, FILE$ returns the name of the file from the last error in an OPEN statement or any other I/O statement.

Comments and Examples

FILE$(0) returns the device name for the current workstation. This function can be used to determine whether a program is running on a DOS or Unix / Linux system. DOS versions will return CON:, whereas Unix / Linux versions will return a string beginning with :/dev/tty. See the SYSTEM command for a detailed example of using FILE$(0) to increase portability of operating system dependent SYSTEM commands.

FILE$(0) will now be displayed without a leading colon if OPTION 25 is specified. In 3.9, File$(0) displays with a leading colon to signify that it is not a normal data file.

As in the following example, the string returned by FILE$ may be used as a valid file name
00010 OPEN #1:"name="&FILE$(0),DISPLAY,OUTPUT

FILE$(fileno,”HTTPINFO”) returns LOG info for the latest action, important while OPENing DISPLAY files.

Related Functions

For additional information about files, see the following functions:

Technical Considerations

  1. If the current error was not an I/O error, FILE$ will be irrelevant because it contains information about a previous error.


FILENUM

FILENUM

The FileNum internal function returns the number of the file that produced the most recent I/O error.

Comments and Examples

A generalized error-handling routine could include the following statement to print the file number of the file with an error:

09000 PRINT "File";FILENUM;"had an error."

File$ with no parameters now provides the same information as FileNum. File$ with no parameters even provides the file name when the error was that the file could not be opened, and thus has no file number.

Related Functions

For additional information about files, see the following functions:

Technical Considerations

  1. If the current error was not an I/O error, FileNum will be irrelevant because it contains information about a previous error.


FKEY

FKEY(<value>)

See also FKEY (Disambiguation)

The FKey internal function is similar to CmdKey, but returns more information, particularly about how a field is exited. A HotKey is very similar to either of these, but is different in that hotkey is not a control word, statement, nor internal function. HotKey is simply a term that refers to an assigned FKey value. Hot key (Fkey) values can be assigned via a print fields or input fields statement that makes a control clickable. Fkey values can also be assigned to entire windows to make the window trigger an interrupt when it is clicked.

Additionally, when an Input Field is assigned an Fkey value and Enter is pressed while the cursor is in that field, or the field is double clicked, then that fkey number is assigned to the internal FKEY variable and, if that value is preset to take action, then that interrupt occurs. OPTION 48 causes BR to disregard Fkey value assignments when Enter is pressed (FKEY is set to zero).

The following table shows a comparison of the values that are returned by FKey and CmdKey when a particular key is pressed to terminate field input. Fkey values above 100 do not cause INPUT FIELDS to terminate processing, but when control is returned to a program for other reasons the FKEY internal function can be used to determine what was keyed.

FKey(X) sets the value of FKey to X. It also sets the value of CmdKey. However, if X is greater than 91 then CmdKey is set to zero. Likewise, the function CmdKey(X) sets both CmdKey and FKey to the value of X.

Keyboard Mapping for FKeys

Key Shifted FKey Interrupt (qwerty) Control Details
Plain Shifted Alt
a A 30 0
b B 48 90
c C 46
d D 32
e E 18 113
f F 33 91
g G 34 111
h H 35
i I 23 110
j J 36 104
k K 37 102
l L 38 116
m M 50 0
n N 49 103
o O 24 115
p P 25
q Q 16
r R 19 105
s S 31
t T 20 106
u U 22 114
v V 47
w W 17 112
x X 45
y Y 21 100
z Z 44
1 !
2 @ 121
3 # 122
4 $ 123
5 % 124
6 ^ 125
7 & 126
8 * 127
9 ( 128
0 ) 129
` ~
- _ 130
= +
[ { 99
] }
\
; :
' "
, <
. >
/ ?
tab 110 111
field+ 114
field- 115

Note that BR retains select (hilite) status while shift or control remain depressed after a program receives control in navigation mode. When in edit mode, the control key temporarily switches to navigation mode.

*In the following chart, the asterisks denotes a change that occurred with version 4.3. Most of the keys in prior versions were unassigned, but a few were assigned differently.

Key Shifted FKey Interrupt (qwerty) Control Details
Plain Shifted Alt
enter 0 0 0 0
home 112 112* 112 112
end 113 113* 113 113
pageUp 90 90 90 90
pageDn 91 91 91 91
up-arrow 102 102* 102 102* FIELDS
down-arrow 104 104* 104 104* FIELDS
left arrow 103 103* 103 103* FIELDS
right arrow 116 116* 116 116* FIELDS
up-arrow 105 105 105* 105* SELECT
down-arrow 106 106 106* 106* SELECT
left arrow 108 108 108* 108* SELECT
right arrow 109 109 109* 109* SELECT
left click 200
second left 201
right click 100
second right 101
wheel up 124
wheel down 125
F1 1 11 1 21
F2 2 12 2 22
F3 3 13 3 23
F4 4 14 93 24
F5 5 15 5 25
F6 6 16 6 26
F7 7 17 7 27
F8 8 18 8 28
F9 9 19 9 29
F10 10 20 10 30
F11 11 21 11 31
F12 12 22 12 32

Standard FKeys

FKey value Cause Additional
1 F1
2 F2
3 F3
4 F4
5 F5
6 F6
7 F7
8 F8
9 F9
10 F10
11 F11 or Shift+F1
12 F12 or Shift+F2
13 Shift+F3
14 Shift+F4
15 Shift+F5
16 Shift+F6 or Alt+Q
17 Shift+F7 or Alt+W
18 Shift+F8 or Alt+E
19 Shift+F9 or Alt+R
20 Shift+F10 or Alt+T
21 Ctrl+F1 or Alt+Y
22 Ctrl+F2 or Alt+U
23 Ctrl+F3 or Alt+I
24 Ctrl+F4 or Alt+O
25 Ctrl+F5 or Alt+P
26 Ctrl+F6
27 Ctrl+F7
28 Ctrl+F8
29 Ctrl+F9
30 Ctrl+F10 or Alt+A *
31 Ctrl+F11 or Alt+S *
32 Ctrl+F12 or Alt+D *
33 Alt+F *
34 Alt+G *
35 Alt+H *
36
37 Alt+K *
38 Alt+L *
39
40
41
44 Alt+Z *
45 Alt+X *
46 Alt+C *
47 Alt+V *
48 Alt+B *
49 Alt+N *
50 Alt+M *
90 page up
91 page down
92 tab change
93 Application Exit, Alt+F4 or Big X An Option exist to reassign this to a different value
98 Drop Down Menu ??
99 Escape or Alt+J *
100 Ctrl+Y
104 AE field exit
105 AE field exit
106 AE field exit
107 AE field exit
110 AE field exit (Tab)
200 click
201 Double Click (Requires Option (config) 52)
* Alt+Key combinations will not work if a drop down menu co-exists with that letter specified as hot (with a &) at any level of the menu.


FKey 200 and FKey 206 are similar. On windows machines with single click enabled a 200 will be returned instead of a 206.

From a GRID with AEX attributes

These have been tested and should probably be added to the the chart above.

FKey value Cause Additional
91 Ctrl+Left
110 Tab
111 Shift+Tab
112 Home
113 End
114 Field Plus (+) (the Plus key on the number pad)
116 Right
120 Ctrl+End or Shift+End
126 Ctrl+Up
127 Ctrl+Down
133 Shift+Left
134 Shift+Right
135 Shift+Up
136 Shift+Down
200 Double Click (sometimes - also 201) Also Click on windows machines with the single click preference enabled.
201 Double Click (sometimes - also 200) (Requires Option (config) 52)
206 Click

From a GRID with LX attributes

FKey value Cause Additional
124 Mouse Wheel scroll up
125 Mouse Wheel scroll down

From a TextBox with AEX attributes

These have been tested and should probably be added the the chart above. FKey values listed in the GRID with AEX section above are not duplicated here.

FKey value Cause Additional
102 Up
103 Left (from leftmost position)
104 Down

From a GRID with L attributes

FKey value Cause Additional
105 Attempt to Scroll past top
106 Attempt to Scroll past bottom

KStat Only

The KSTAT$ internal function will return a few additional FKey values which Input Fields and Input Select will not. These FKeys are as follows:

FKey Description
176 Click
177 Second Click in Double Click
180 Right Click
181 Second Click in Double Right Click

Combobox Only

Combo Boxes that contain the x attribute often return FKey 209 in such cases use curfld(curfld,fkey) to avoid blinking.

 00010 do
 00020    rinput #win,fields mat io$,attr '[A]': mat setting$,choice_policy$,choice_desc$
 00030    if fkey=209 then let curfld(curfld,fkey)
 00040 loop until fkey<>209

Hot Windows

For versions 4.2 and higher FKEY= may now be specified in an Open Window statement. This makes the window hot, so a user can click anywhere in the window to tell the program that they want to switch focus. The FKEY value is then inheritable, but not to independent windows. In other words, assigning an FKEY value to a window automatically assigns the same FKEY value to it's child windows, unless another FKEY ( or -1 ) is assigned to a child.


FP

FP(<numeric expression>)

The FP internal function returns the fractional part of X.

Comments and Examples

00010 print FP(3.1)
00020 print FP(-3.1)

Output:

0.1
-0.1

Related Functions:


FREESP

FREESP(<file name>)

The FreeSp internal function will return the number of free (unused) bytes on the drive containing file N.

Comments and Examples

00010 OPEN #1:"name=c:BRConfig.sys",DISPLAY,INPUT
00020 LET DRIVE$=FILE$(1:2) ! substring
00030 PRINT "Drive ";DRIVE$;" has";
00040 PRINT FREESP(1);" bytes available"

Related Functions

For additional information about files, see the following functions:


HELP$

HELP$("[*]<topic>[,<filename>]"[,<mark>])

The Help$ internal function displays a help screen. "Topic" is the name of the help topic to be displayed. The "filename" is optional. When a file name is not specified, the system uses the file named in the HELPDFLT specification in the BRConfig.sys file or with the CONFIG command. If HELPDFLT has not been coded and HELP$ is used without a file name, an error will occur.

If the topic name starts with an asterisk (*), the screen is not saved or restored by the help call. The asterisk has no affect on the search for the topic within the text.

"Mark" is an optional number that indicates which part of the topic text to display first. It correlates to a caret (^) character in the text. If mark is specified as 3, the text located after the third caret in the topic text will be displayed on the screen first, although the operator still will be able to review all text associated with the topic.

Comments and Examples

110 LET X$ = HELP$("HOURS.ENTRY",CURFLD)

Related Functions

Technical Considerations

See Help Facility for information about preparing and using on-line help screens.


HEX$

 HEX$(<string>)

The Hex$ internal function returns the string represented by A$, where A$ is in hexadecimal notation.

Comments and Examples

This function is frequently used to send a group of special characters to a printer.

00010 PRINT #255,USING 20: HEX$("1B51")
00020 FORM C 2,SKIP 0

Line 10 sends Esc and Q (ASCII values 1B and 51 in hexadecimal) to the printer. The SKIP 0 in line 20 makes sure that the printer stays on the same line (no line feed is added to the PRINT statement).

An additional common use of HEX$ is to activate printer translation as specified by PRINTER specifications in BRConfig.sys file. PRINTER specifications provide a way to minimize hardware differences between printers, usually without any program changes. All printer translations must begin with ASCII character 2B in hexadecimal notation, i.e., HEX$("2B"). There are more complex rules for valid values of the second character, but 00 will always work. Thus, many programs include HEX$("2B00") to begin printer translation. For more information, see the PRINTER specification in the BRConfig.sys section.

Related Functions

UnHex$ (Inverse of Hex$)


INF

INF

The Inf internal function returns the largest possible number in Business Rules! on the current system. For current DOS, Network, Unix and Linux systems, Inf is 1.000000E+307. To find the smallest number, use PRINT 1/INF.

Comments and examples

00010 print inf   ! prints the largest  number in BR
00020 print 1/inf ! prints the smallest number in BR

Inf may be used to append more characters to the end of a string


To append string2$ to string1$ means to join string2$ to the end of string1$.

To append to the end of a String you should (for maximum speed of code execution) use

X$(inf:0)="append this to end"

OR

X$(inf:inf)="append this to the end"

Here, inf denotes infinity.

So X$(inf:inf) means "the substring of X$ starting at infinity". This is particularly useful when you don't know how long your string is and do not want to calculate its length.

see also: prepend



INT

The INT internal function is identical to IP internal function.

INT(<numeric expression>)

The Int internal function returns the largest integer less than or equal to X.

Comments and Examples

INT(+5.1) is 5, but INT(-5.1) is -6.

Related Functions:

Technical Considerations

When set to 0, the RD specification in BRConfig.sys can affect the INT function.



IP

IP(<numeric expression>)

The IP internal function returns the integer part of X.

Comments and Examples

00010 print IP(5.1)
00020 print IP(-5.1)
00030 print IP(3)

Output:

5
-5
3

Related Functions

Technical Considerations

  1. When set to 0, the RD specification in BRConfig.sys can affect the IP function.


KLN

KLN(<file number>[,<numeric expression>])

The KLn internal function returns the key length in bytes for master file specified by 'file number'. With an optional second parameter, KLN can also return the length of a section of a key when split keys are used. When the numeric expression is 2, the length of the second section of the key is returned.

Comments and Examples

Here is an example to illustrate the use of the optional second parameter for a key file with split keys. In line 1000, file #1 is opened with a key split into three parts. This line replaces the existing master file and the existing key file with newly created empty master and key files.

01000 OPEN #1: "NAME=data,replace,recl=80,KFNAME=key,KPS=70/40/60,KLN=6/7/8",INTERNAL,OUTIN,KEYED

The optional second parameter of the KLN function specifies the key field number when there are split keys. Listed below are values that can be returned by the KLN function after the above OPEN statement for a key field composed of three separate fields:

  KLN(1) = 21
  KLN(1,1) = 6
  KLN(1,0) = 21
  KLN(1,2) = 7
  KLN(1,4) = -1
  KLN(1,3) = 8

KLN(1) returns 21 because it returns the total combined length of the separate key fields for the key file (the key lengths of 6, 7 and 8 are added). Notice that when the second parameter is zero, the result is the same as when the second parameter is omitted. KLN(1,0) is equivalent to KLN(1).

The KLN function returns -1 when the file is not open or the master file has no key file. An invalid key field number will also return -1. For example, KLN(1,4) returns -1 because this file was opened with only three key fields. This result occurs whenever the specified field number is bigger than the number of fields used.

Related Functions


KPS

KPS(<file name> [,<numeric expression>])

The KPs internal function returns the byte position where the key for master file named starts. With an optional second parameter, KPS can also return the position of a section of a key when split keys are used. For example, in KPS(Afile,2), the starting position of the second section of the key is returned.

Comments and Examples

Here is an example to illustrate the use of the optional second parameter for indexes with split keys. In line 1000, file #1 is opened with a key split into three parts. This line replaces the existing master file and the existing key file with newly created empty master and key files.

1000 OPEN #1: "NAME=data,replace,recl=80,KFNAME=key,KPS=70/40/60,KLN=6/7/8", INTERNAL,OUTIN,KEYED

The optional second parameter of the KPS function specifies the key field number when there are split keys. Listed below are values that can be returned by the KPS function with the above OPEN statement for a key field composed of three separate fields:

  KPS(1) = 70
  KPS(1,1) = 70
  KPS(1,0) = 70
  KPS(1,2) = 40
  KPS(1,4) = -1
  KPS(1,3) = 60

KPS(1) returns 70 because it returns the starting position specified first for the key file. Notice that the system does not change the order of parameters; thus, even though position 40 is first physically, KPS returns these numbers according to the order in which they were specified.

The KPS function returns -1 when the file is not open or the master file has no key file. An invalid key field number will also return -1. For example, KPS(1,4) returns -1 because this file was opened with only three key fields. This result occurs whenever the specified field number is bigger than the number of fields used.

Related Functions


KREC

KREC

The KRec internal function:

  1. returns the number of the last accessed key for indexed files
  2. returns the number of records accessed since the last NEWPAGE for display files

Note- following NEWPAGE with a semicolon (e.g. NEWPAGE; ) suppresses the zeroing of KREC.

When processing a linked file, KRec is updated with the location of an anchor record only under the following conditions:

  1. A Rec=(anchor record) is processed.
  2. An anchor record is read.
  3. An anchor record is written or deleted.

Restore REC=(non-anchor)sets KRec to zero. KRec remains otherwise unaffected during Read and Write statement processing.

Comments and Examples

KRec(N) is really two functions under one name. It has one use with display files, and another use with indexed internal files.

When file N is a display file, KRec(N) acts as a line counter for lines output to the file. This feature is especially useful with printers in counting how many lines have already been printed on a page. Also, outputting a NEWPAGE to advance the paper to the top of the next page resets this counter to zero. Print KRec(255) will return the number of lines output to the standard printer file #255 since the last PRINT #255: NEWPAGE was issued.

If file N is an internal file opened for Keyed processing, then KRec(N) returns the number of the last record accessed in the key file. This is different from the last record accessed in the master file, which can be found by the Rec(N) function.

Related Functions

For additional information about files, see the following functions:


KSTAT$

KSTAT[(<numeric expression>)[,<seconds>]]

When used without parameters, the KStat$ internal function will return any keystrokes entered that were not already processed. When used with the numeric parameter, KSTAT$ causes Business Rules! to wait for input of the number of keystrokes specified.

KSTAT$ has a second optional numeric parameter denoting the number of seconds to wait for each character.

Example:

KSTAT$(1,10) ! waits up to 10 seconds for 1 keystroke

Comments and Examples

Special keys such as HOME, END and the arrow keys return their control-key equivalents. All keys return a one-character value except the function keys, which return a two-character value.

When the numeric value is 0, it's the same as KSTAT$ with no parameter. If it is negative, 1 will be used. The dimensioned length of the receiving variable should be at least twice as large as the number passed to prevent a string overflow in the event that all keys pressed are function keys (which return two hex characters instead of one).

In the following example, the use of KSTAT$ in line 100 is preferable to its use in line 300, especially on Unix / Linux terminals. Whereas line 300 ties up the processor as it waits for a keystroke, line 100 idles the task until a key is pressed:

00100 LET X$=KSTAT$(1) ! Wait for 1 keystroke
00300 LET X$=KSTAT$ !:
00400 IF X$="" THEN GOTO 300 ! Wait for keystroke

To determine the standardized Business Rules scancodes, run the following program:

10 LET X$ = KSTAT$(1)
20 PRINT UNHEX$(X$)
30 GOTO 10

Each time you press a key, the scancode for that key is displayed.

Technical Considerations

  1. There are two levels of scancodes: the hardware level and the Business Rules level. If you want to determine the standardized Business Rules scancodes, run the program in the examples section above. In all scancode programs, each time you press a key, the scancode for that key is displayed.
  2. The scancodes from the hardware level are used as input for the wbterm program which defines the scancodes at the Business Rules level. Processing for both levels of scancodes is built into DOS and NetWork versions of Business Rules .



LEN

LEN(<string>)

The Len(string$) internal function returns the number of characters in variable string$.

Comments and Examples

00010 LET A$ = "red"
00020 LET B$ = "white "
00030 LET C$ = "blue"
00040 PRINT LEN(A$);LEN(B$);LEN(C$)

Line 40 will print the numbers 3, 6 and 4.

Related Functions


LINE

LINE

The Line internal function returns the line number of the most recent error. When an error occurs in a procedure while PROCERR RETURN is in effect, LINE is set to -1.

Comments and Examples

Program errors which are not anticipated can be handled by adding the following to any program.

00001 ON ERROR GOTO 99900
 o
 o
99900 PRINT "Unexpected Error Number";ERR
99910 PRINT "occurred at line number";LINE
99920 PRINT
99930 PRINT "Please record this information,"
99940 PRINT "and call your dealer at once!"
99950 PAUSE
99960 CHAIN "MENU"

Related Functions

ERR

Technical Considerations

  1. There are four cases where errors occur and LINE is not set. First, LINE is not changed when an ON error statement (or default) has set to IGNORE the error condition corresponding to this error. Second, when the error code is 4273 (topic not found in help file), the system does not set LINE or ERR so that an error in attempting to use the HELP$ function in an error trapping routine will not affect the ability to use RETRY or CONTINUE. Third, the value of LINE is not affected when an error occurs in an immediate statement which has been keyed in from the keyboard; the error code for this immediate statement is displayed correctly in the status line. Fourth, the value of LINE is not affected when an undefined function causes error code 0302; instead, the name of the undefined function is displayed on the 23rd line of the screen.
  2. LINE is initialized to -1 by the following: the RUN command, PROCERR RETURN command, CLEAR or CLEAR ALL commands and any other commands which clear memory.
  3. When PROCERR RETURN is in effect, and a syntax error occurs during a LOAD SOURCE command, LINE is set to the line number of the previous line (instead of the current, unaccepted line), and control is returned to the procedure.


LINES

LINES(<file number>)

The Lines internal function returns the number of lines printed since the last new page. File number should represent a display file. This function is identical to KREC as used with display files, just more appropriately named.


LINESPP

LINESPP(<file number>)

The LINESPP internal function supports programs that are sensitive to various page lengths. It returns the current lines per page as set by a BRConfig.sys PRINTER spec's LPP parameter or 66 by default. If an LPP value is specified in a BRConfig.sys PRINTER spec, LINESPP will return that value after that PRINTER substitution has been used by a PRINT statement.

In the following example, the unbracketed "LPP 48" parameter sets the value of LINESPP to 48. In the code fragment that follows, line 30 executes a PRINT statement that utilizes the PRINTER substitution. At that point, the value of LINESPP is changed to 48.

PRINTER LPP 48 [SET48],"\\Ep48"
10 OPEN #255:"NAME=PRN:/10",DISPLAY,OUTPUT
20 PRINT LINESPP(255)
30 PRINT #255:"[SET48]"
40 PRINT LINESPP(255)

Program output would be:

66
48

This feature was designed to support the transparent use of both dot matrix and laser printers on the same system. When printing reports that require more than 80 columns or more than 132 columns, a number of options exist to print that same report in landscape mode, which changes the number of printable lines per page.

The following is a table showing the common columns per page and the mode required for dot matrix and laser printers:

Also, since many laser printers have scalable fonts or font cartridges, a larger point size may be chosen for [COLS=132]. Without any extra program code, simply select the number of columns needed for the report from the above list:

PRINT #255,USING "FORM C,SKIP 0":"[COLS=132]"

and use LINESPP to get the number of lines per page in this format:

MAXLINES = LINESPP(255)


LOG

You may be looking for Logging.


The Log internal function returns the natural logarithm of its argument. This is like the LN(X) function in mathematics. Do not confuse the BR LOG with the mathematical LOG base 10.

LOG(<positive number>)

The argument must be a positive number.

00010 print LOG(2.718)

produces the following output:

0.999896


However,

00010 print LOG(-3)

produces an error


LOGIN_NAME$

LOGIN_NAME$

Login Name$ can refer to the CONFIG parameter or the internal function:

Config

The Login_Name$ BRConfig.sys specification may be substituted during BRConfig.sys statement interpretation. Specify LOGIN_NAME$ (case insensitive) anywhere in a BRConfig.sys statement to have the user's name appear in the statement. For example:

DRIVE G:,G:\\HOME\\[LOGIN_NAME$],zz,\\

Defines drive G: as the user's home directory.

You can also SET the LOGIN_NAME$ with LOGIN_NAME$("newname").

Internal Function

The Login_Name$ internal function contains the operating system user login name. This can also be set with LOGIN_NAME$("newname").

The priority of the LOGIN_NAME variable setting is:

1) BR startup command parameter (@name)
2) Workstation operating System user login name
3) BRCONFIG.SYS "LOGIN_NAME name" statement

These alternatives support the assignment of login name in all models. This can significantly simplify the tailoring of BRCONFIG.SYS files through use of the @name statement prefix. Instead of having to place a separate BRCONFIG.SYS file on each client system, the client's could specify the login name of the user, and a common BRCONFIG.SYS file could contain the custom statements for all users, beginning the custom statements with @name for each login name. For example:

BR  @myname  run menu

BRCONFIG.SYS includes:

@myname WSID 25
@myname PRINTER OKIDATA

@UserName in the BR startup command may also be used to override the windows environmental variable UserName in the Login_Name$ internal function.


LPAD$

LPAD$(<string>$,<length>[,"<character>"])

The LPad$ internal function returns the string$, adding leading blanks to make it "length" characters long. If the string$ already has at least that many characters, no blanks are added.

Comments and Examples

10 LET A$ = "Right-justify"
20 LET B$ = "Right-edge"
30 PRINT LEN(A$),LEN(B$)
40 LET A$ = LPAD$(A$,13)
50 LET B$ = LPAD$(B$,13)
60 PRINT LEN(A$),LEN(B$)

The above example will print 10 and 13 from line 30, but will print 13 and 13 from line 60 after both strings have been left-padded with blanks.

An optional third parameter ("character") has been added to LPAD$ and RPAD$ to specify the character to be used for the padding (instead of blanks, which are still the default). The "character" parameter is limited to one character in length (error 410 will result if it is longer). Nulls and CHR$(0) are allowed.

See Also

Technical Considerations

  1. If the left padding is being done only to improve the output format, the CR format specification provides an alternative that executes faster, takes less time to code, and uses less program space.


LREC

LREC(<file handle>)

When the file referred to is an internal file, LRec internal function returns the number of the last record in the file. When it's an external file, LRec returns the last record or last byte (depending on whether REC= or POS= was used last). When it's a display file, LREC returns the byte size of the file.

When the file is not an open internal file handle LRec will return 0 or -1. If the file handle is equal to, then LRec will return 0. If it's greater than zero but is not an open file handle, LRec will return -1.

Comments and Examples

Here are three quick steps to determine how many records are in an internal file:

00010 OPEN #1:"name=filename",I,I,S
00020 PRINT LREC(1)
00030 CLOSE #1:

As long as there are no deleted records, the number printed by PRINT LREC(1) is the total number of records in file 1.

Related Functions

For additional information about files, see the following functions:

Technical Considerations

  1. If any space in the file is occupied by records marked for deletion by the DELETE statement, these records will still appear in the total from LREC(N) even though they will not be processed by reading the file sequentially.
  2. If file N is not open, LREC(N) will return -1.
  3. For external files, LREC(N) can return either a record number or a byte number, depending on whether the last I/O statement used a REC= clause (the default mode) or a POS= clause (to position to a specified byte number).
  4. The use of LREC within an I/O statement is strongly discouraged, especially on multi-user systems. See the Multi-user Programming chapter for additional information.


LTRM$

LTRM$(<string>,"<chr>")

The LTrm$ internal function deletes leading blanks from the variable. So named, because it left-trims the blanks from the string.

Comments and Examples

When an operator enters a character string which will be used as a key field (such as last name), any spaces on the front part of the name will probably cause the string entered to not match anything in the key file. To minimize these errors, the program can remove any leading spaces with the LTRM$ function. However, when LTRM$ successfully removes one or two spaces from the beginning of the string, this causes another problem because now the string is one or two characters shorter; this second problem can be solved by adding spaces on the right with the RPAD$ function. Combining these two functions as in line 430 below is a common data clean-up technique.

An optional second parameter ("char") has been added to LTRM$ and RTRM$ to specify the character to strip (instead of blanks, which are still the default). The "char" parameter is limited to one character in length (error 0410 will result if it is longer). Nulls and CHR$(0) are allowed. The following statement would return the value 12:

00410 PRINT FIELDS "10,30,C 20: "Enter LAST NAME"
00420 INPUT FIELDS "12,30,C 10,R": LNAME$
00430 LET LNAME$ = RPAD$(LTRM$(LNAME$),10)
00440 READ #2,USING 450,KEY=LNAME$: ADDRESS$,CITY$,ST$

Related Functions

See RTRM$ to trim blanks from the right and LPAD$ and RPAD$ to add blanks.


LWRC$

LWRC$(<string>)

The LwrC$ internal function converts any uppercase letters in the string to lowercase letters.

Comments and Examples

10 LET A$ = "E. E. Cummings"
20 PRINT LWRC$(A$)

Line 20 will print:

e. e. cummings

Related Functions

See the UPRC$ function for conversion from lowercase to uppercase.

Technical Considerations

  1. Another method for conversion to lowercase is the CL, VL and GL format specifications, which are effective only with INPUT FIELDS and RINPUT FIELDS. This method converts keystrokes, as they are being entered, into lowercase only. See also the CU, VU and GU format specifications for more information about converting incoming keystrokes to uppercase.


MAT2STR

Business Rules! 4.20 introduces the Mat2Str internal function which converts an array to a string

mat2str(MAT <Array Name>, <String Variable> [, [MAT] <Delimiter$>] [, "<Quote-Type>] [:] [<trim>]")

Parameters

"MAT Array Name" is the source array, from which you are building a string.

"String Variable" is the destination string that the function is creating.

"MAT Delimiter$" is a character that will be put after every entry from the array including the last entry. The delimiter can be "" which would simply concatenate the array. It is optional. As of 4.3 it can be an array.

"Quote Type" is optional, can be "Q", "QUOTES" , ' or " and is used to add quote processing to the string. This means that either a single or double quote will be placed around each of the source array's elements while creating the string. It's case insensitive.

If Q or QUOTES is specified then BR determines which quote type to apply like this: If the first element is contained in quotes, the quotes are stripped and any two consecutive quotes of the same kind become singles. Next the element is scanned left to right for either type of quote character (single or double). If a quote character is encountered the element is enclosed in the alternate quote type and embedded occurrences of that quote type are doubled. If no quote character is encountered then double quotes are applied.

"Trim" can be :LTRM , :TRIM or :RTRM and signifies the trim pre-processing of array elements. The colon is only used if preceded by a quote type.

Quote Processing Examples

Quote Type is Q or QUOTES

Array Element Part in the String Explanation
abcdef "abcdef" Normal processing of double quotes
abc'def "abc'def" A single quote embedded in an array element remains embedded in the string
abc"def 'abc"def' A double quote embedded in an array element remains embedded in the string
abc""def 'abc""def' Embedded quotes are left intact when quotes are not active
'abcdef "'abcdef" One single quote will be included in the string's double quotes.

Quote Type is ' (quote type single) When quote type is double, it mirrors quote type single.

Array Element Part of the String Explanation
abcdef 'abcdef' Normal processing of double quotes
'abcdef '''abcdef' A leading single quote is duplicated when embedded in single quotes
"abcdef '"abcdef' Leading double quote is included within the single quotes, like any other character

MAT2STR and STR2MAT trim outside of quotes but not inside of quotes.

MAT2STR always adds quotes when quotes are present in the data.

Defaults

1. The default Delimiter$ is CR on Linux or CRLF on Windows.

Other

1. Mat2Str performs the opposite action of Str2Mat.

2. Remember to dimension your resulting string.

3. When using MAT2STR on a 2 dimensional array, the first delimiter is used for individual elements and the second delimiter at the end of each row. This principle also applies to arrays containing three to seven dimensions. For example, given the following two dimensional array zzz$ containing the values:

   1            2
   3            4

The following statements-

00010 Sep$(1)=","
00020 Sep$(2)=hex$("0D0A") ! CRLF
00030 MAT2STR( MAT zzz$, str$, MAT Sep$ )
00040 PRINT str$

Will produce-

   1,2
   3,4

Examples

In the following code, we are making an array into a string separated by commas for printing.

! make the codes into one string for printing
let mat2str(Mat code$, MainString$, ",", "Q:trim")
print "The allowable codes include the following: "&mainstring$&"."

The output is as follows:

Without the "Q:trim", it would appear like this:

Example 2:

00010 dim resulting_String$*100, array$(3)
00020 let array$(1)="first"
00030 let array$(2)="second"
00040 let array$(3)="third"
00050 mat2str(mat array$,resulting_String$,"//")
00060 print resulting_String$

Output:

first//second//third


MAX

MAX(<value>,<value>[,...])

The Max internal function returns the largest numeric value in the set of numbers inside parentheses (X1, X2 and so on).

Comments and Examples

10 LET A = 8
20 LET B = 10
30 LET C = 5
40 PRINT MAX(A,B,C)

The above program will print the number 10.

Related Functions

MAX$ is a similar function for strings. MIN and MIN$ return the smallest values.

Technical Considerations

  1. The number of items that can be listed inside the parentheses is limited only by the maximum line length of 800 characters in source code or 255 characters in compiled code.


MAX$

MAX$(<string>$,<string>$[,...])

The Max$ internal function returns the largest string value in the set of strings inside parentheses (A1$, A2$ and so on). When comparing strings, the largest value is the one with the highest ASCII value. If only letters of the alphabet are being compared, MAX$ will return the string that is last in alphabetical order.

Comments and Examples

10 LET A$ = "red"
20 LET B$ = "green"
30 LET C$ = "blue"
40 PRINT MAX$(A$,B$,C$)

The above program will print the string "red" (without the quotation marks).

Related Functions

MAX is a similar function for numbers. Similarly, MIN$ and MIN return the smallest values.

Technical Considerations

  1. The number of items that can be listed inside the parenthesis is limited only by the maximum line length of 800 characters in source code or 255 characters in compiled code.
  2. The COLLATE option in effect when the program was last saved or in the OPTION statement can alter the string comparisons within the MAX$ function.


MIN

MIN(<value>,<value>[,...])

The Min internal function returns the smallest numeric value in the set of numbers inside parentheses (X1, X2 and so on).

Comments and Examples

10 LET A = 8
20 LET B = 10
30 LET C = 5
40 PRINT MIN(A,B,C)

The above program will print the number 5.

Related Functions:

MIN$ is a similar function for strings. MAX and MAX$ return the largest values.

Technical Considerations

  1. The number of items that can be listed inside the parenthesis is limited only by the maximum line length of 800 characters in source code or 255 characters in compiled code.


MIN$

MIN$(<string>,<string>[,...])

The Min$ internal function returns the smallest string value in the set of strings inside parentheses (A1$, A2$ and so on). When comparing strings, the smallest value is the one with the lowest ASCII value. If only letters of the alphabet are being compared, MIN$ will return the string that is first in alphabetical order.

Comments and Examples

10 LET A$ = "red"
20 LET B$ = "green"
30 LET C$ = "blue"
40 PRINT MIN$(A$,B$,C$)

The above program will print the string "blue" (without the quotation marks).

Related Functions

MIN is a similar function for numbers. Similarly, MAX$ and MAX return the largest values.

Technical Considerations

  1. The number of items that can be listed inside the parentheses is limited only by the maximum line length of 800 characters in source code or 255 characters in compiled code.
  2. The COLLATE option in effect when the program was last saved or in the OPTION statement can alter the string comparisons within the MAX$ function.


MOD

The Mod internal function returns the remainder of the numerator divided by the denominator. In other words, it is the remainder left after the division of one integer by another

MOD(<numerator>, <denominator>)

Comments and Examples

For example, 7 divided by 3 equals 2 with a remainder of 1. Consider the following code snippet:

00010 print MOD(7,3)
00020 print MOD(6,3)
00030 print MOD(5,3)

Output:

1
0
2

See also Rem (Internal Function).


MSG

MSG("<KB>",<string>) ! send string to keyboard

The MSG internal function (without the dollar sign) is only available for Windows & CS versions. This should not be confused with Msg$. For example:

MSG("sleeptime",centiseconds) ! specify MSG keystroke time interval (100 = 1 Second)

With the Msg internal function you can directly control the keyboard under the Windows client from within a BR program by issuing a function call to MSG.

Msg is useful for redisplaying Windows menus upon returning to a menu program from an application program. MSG has no effect on Unix or Linux terminal sessions, but works under Client / Server with Unix the same as WINDOWS.

The first parameter ("KB" or "kb") is case insensitive.

Two new Error Codes are defined in support of this function:

  • 0412 Invalid Action Code - The first parameter is not recognized.
  • 0413 Window Not On Top - A KB message was sent to a task which is different from the one that currently owns the keyboard.

Note that the following error codes may be related to this function:

  • 0414 Wrong number of arguments passed
  • 0415 Some error that has err message
  • 0416 Not enough elements in dimensioned array
  • 0417 Dimensioned string length is not big enough
  • 0418 Unknown
  • 0419 Error in special char spec

Special Keystroke Values

This facility operates through the operating system, so it does not utilize BR scancodes. If you need to send a special character (which in turn may cause BR to generate its scancodes), you will need to emulate the corresponding keyboard activity. Special characters need to be enclosed in pipes |.

Examples

If you want to send ctrl+c, you must send the following string:

00010 MSG("KB","|CTRL+|c|CTRL-|")

This says that you want depress the "CTRL" key, type "c", and then release "CTRL".


Example:

MSG("KB","|CTRL+|p|CTRL-|")

Will input the CTRL-P character, which causes BR to perform a printscreen operation.

Special Character List

Each char must be enclosed in pipes

ALT+ press ALT - see note below
ALT- release ALT
CTRL+ press CTRL
CTRL- release CTRL
SHIFT+ press SHIFT
SHIFT- release SHIFT
TAB press the tabulation key
RET press the return key
ESC press the escape key
BACK press the backward key
DEL press the delete key
INS press the insert key
HELP press the help key
LEFT send the cursor to the left (left arrow)
RIGHT send the cursor to the right (right arrow)
UP send the cursor up (up arrow)
DOWN send the cursor down (down arrow)
PGUP press the page up key
PGDN press the page down key
HOME press the home key
END press the end key
F1 press the function key F1
F2 press the function key F2
F3 press the function key F3
F4 press the function key F4
F5 press the function key F5
F6 press the function key F6
F7 press the function key F7
F8 press the function key F8
F9 press the function key F9
F14 press the function key F14
F11 press the function key F11
F12 press the function key F12
NUM0 press the 0 on the key pad
NUM1 press the 1 on the key pad
NUM2 press the 2 on the key pad
NUM3 press the 3 on the key pad
NUM4 press the 4 on the key pad
NUM5 press the 5 on the key pad
NUM6 press the 6 on the key pad
NUM7 press the 7 on the key pad
NUM8 press the 8 on the key pad
NUM9 press the 9 on the key pad
NUM* press the * on the key pad
NUM+ press the + on the key pad
NUM- press the - on the key pad
NUM, press the , on the key pad
NUM/ press the / on the key pad

To send the pipe character specify |||.

MSG("sleeptime",seconds) specifies the number of seconds to wait before issuing each string and each control character. Seconds may also be expressed with *up to three decimal digits* The default value is 0.2 seconds.

Please note that the ALT key needs to be depressed and released (ALT+ and ALT-) for every Alt-character specified.

|alt+|m|alt-||alt+|b|alt-| works

|alt+|mb|alt-| fails

|alt+|m|down||alt-| works

This is because keyboard entries don't interpret more than one keystroke as an alt value except when using the numeric keypad. However Windows will honor arrow keys while the alt key is held down.


MSG$

The Msg$ internal function displays information in the second box of the command console.

Msg$("<text>")

See also

Execute "Config Status Off Message Text" as discussed in Seldom Asked Questions.

Please note this Msg$ internal function is similar only in name to the Msg internal function. There are no other similarities.


MSGBOX

MSGBOX (<PROMPT$>[, <TITLE$>][, <BUTTONS$>][, <ICON$>])

The MsgBox Internal Function will display a Windows Message Box. It has four possible parameters:

  • PROMPT$
  • TITLE$
  • BUTTONS$
  • ICON$

PROMPT$ is the only required parameter. It is a string which is to be displayed within the message box.

TITLE$ is a string containing the title of the message box.

BUTTONS$ indicates which buttons will be displayed in the message box. If you don't specify a button configuration the OK button is displayed.The value of the button the user selects is returned to BR in CNT.

The BUTTON$ value that is capitalized will become the default button (selected by the Enter key). For example, if "Yn" or "Ync" is specified then the Yes button becomes the default button. If "yN" or "yNc" is specified then the No button is displayed as the default button. The case of the "c" has no bearing on default button focus. If both or neither are capitalized, ie: "YN" or "yn", then the default is that YES is pre-selected.

Acceptable values for BUTTONS$

OK Displays OK button (default)
YN Displays Yes and No buttons
OKC Displays OK and Cancel buttons
YNC Displays Yes, No and Cancel buttons


ICON$ indicates what ICON, if any, will be displayed. If you don't specify a title, a blank title bar is displayed. All ICON$ values are case insensitive.

Acceptable values for ICON$

INF Displays (i) Information icon
ERR Displays Error Icon, which is a stop or a red x sign (depends upon OS)
EXCL Displays Exclamation Point
QST Displays a Question Mark

Examples

00010 Let MSGBOX( PROMPT$, TITLE$, BUTTONS$, ICON$)
00020 Let VALUE= MSGBOX( "Record not Found", "Error", "OK", "ERR")
00030 Let MSGBOX( "End of Data", "NOTE")


Complete Example
00060   MsgBox('Are the labels aligned correctly?', 'check Printer', 'Yn', 'Qst')><2 then goto ALIGN

The example above will produce a message box like the image below. "Yes" is the default button and will have an added border identifying it as such when running the program.

Returned Values

Possible return values are:

0 An error occurred such as not enough memory. (This is quite rare.)
1 The OK button was selected.
2 The YES button was selected.
3 The NO button was selected.
4 The CANCEL button was selected, or ESC was pressed. (The ESC key has no affect when the Cancel button is not displayed.)

In our example, if YES is not selected, it will return to the program and go to the line label ALIGN, which turns out to be another message box about aligning paper in the printer. If YES is selected, it simply continues with the program to print the labels:

00060   MSGBOX(PROMPT$, TITLE$, BUTTONS$, ICON$)><2 then goto ALIGN

Line breaks in a message box

To force a new line in the text of a message box insert a CHR$(13) or HEX$("0D0A"), carriage return, in the text at the point where the word wrap should occur. If no line is forced Windows will determine a wrap point based on the width of the monitor.

For example (and demonstrating the EXCL icon):

00100 let prompt$="Did you already run the ENDOFMONTH program?"&hex$("0D0A")&"If you did not, and continue anyways, records may be lost."&hex$("0D0A")&hex$("0D0A")&"Well - DID YOU?"

Two &hex$("0D0A") in a row will display a completely skipped line.


NEWPAGE

NEWPAGE

The NewPage internal function returns a character which, when printed, causes the printer to do a form feed or the screen to clear.

Comments and Examples

00010 PRINT NEWPAGE
00020 PRINT BELL,NEWPAGE,"ERROR"
00030 PRINT #255: NEWPAGE

Line 10 erases the screen. Line 20 sounds the tone, clears the screen and prints the message ERROR at the bottom of the screen. Line 30 advances the printer to the top of the next page (sends a character for FORM FEED). NEWPAGE also resets internal line counting variables (see Technical Considerations below in this section).

The NEWPAGE function no longer outputs a carriage return to display files when used in the following form:

PRINT #255: NEWPAGE

Previously, NEWPAGE would output both the newpage character (FF-chr$(12)) and a carriage return (CR - chr$(13)) character. The carriage return has been removed because some printers were using it to move the paper up an extra line, or they weren't recognizing the escape sequences that followed it. Be aware that this may affect printed or spooled reports.

Related Functions

Other special functions used mainly in PRINT are BELL and TAB(X). Also, the KREC(N) function for display files will count the number of output lines since the last NEWPAGE was issued.

Technical Considerations

  1. NEWPAGE also zeroes the internal line counter used by the PAGEOFLOW error condition to perform page breaks. This counter can be displayed or printed with the KREC(N) function. For example, KREC(255) tells how many lines of output have been sent to the printer since the last NEWPAGE was issued.
  2. In an unformatted PRINT statement, when NEWPAGE precedes the TAB(X) function, the TAB function will appear to be off by one column because the character for NEWPAGE appears in the output buffer, but not on the screen or printer. Avoid using NEWPAGE (or BELL) before TAB in an unformatted PRINT statement. One remedy is to use one PRINT statement for NEWPAGE (and BELL) and another for the TAB function and other output.


NXTCOL

The NxtRow, Next, and NxtCol internal functions were introduced in BR! 4.20.

Related functions are Next and NxtRow.

The keyword Next can be used in the same manner as CUR in that the next cursor position within a 2D control can be identified.

00100 INPUT FIELDS "row,col,GRID 10/60, SUB, NEXT, NOWAIT": next_pos

The NxtCol internal function identifies the character position or cell column associated with the next cursor position (e.g. where the mouse was last clicked). If the next cursor position is in Grid or List, then NxtCol identifies the cell that was clicked. If not a 2D control, it specifies the first character position of the next control to receive focus.

NxtRow specifies the row of the respective position.

With respect to these functions, the next cursor position can be the result of keyboard or mouse activity. If the next position results from keyboard activity then NxtRow has the same value as CurRow when Enter is pressed or control was returned in response to a leading attribute such as X (return control upon exit). When the mouse is used to return control to a program, the next cursor position is the pointer location that is double clicked or hot location that is single clicked.

One key concept here is that just as one must keep track of what type of control was last accessed, by means other than CurRow and CurCol, similarly **one must determine the type of control to be next accessed by means other than NxtRow and NxtCol**. This can be done with the system function NxtFld plus hotkey event (fkey) numbers.

CurCol/NxtCol have a slight change in functionality in 4.20 release. Previously they specified the column (relative to the window) of the cursor position. Now they specify the first position of the respective control.

Option 59 has been added to make CurCol (not NxtCol) work the old way.


NXTFLD

The NxtFld internal function is similar to Curfld except that it returns the relative position of the next control to be occupied during an INPUT operation (the one the user clicked on or attempted to move to).

Two methods are used to identify clicked controls: Fkey numbers and NXTFLD. This will keep track of which control was clicked when a user clicks on a hot control (a control that has an Fkey assigned). If the control is a GRID or LIST then it keeps track of where the user clicked within the control.

If a control that is part of an active Input Fields operation is double clicked, then NXTFLD will identify the relative position of the control within the Fields operation. However, for hot field identification it is necessary to use Fkey values to identify the respective controls.

Interrogating the Next Control

It is desirable to know which control was clicked when a user clicks on a hot control (a control that has an Fkey assigned). Furthermore, if the control is a GRID or LIST then it can be useful to know where the user clicked within the control. Two methods are used to identify clicked controls: Fkey numbers and NXTFLD.

The NxtFld internal function has 4 possible combinations of syntax:

NXTFLD
 
NXTFLD([<New_current_field>] [,<attribute$>] [,FKEY])

NXTFLD([<New_current_field>] [,<New_current_row>]) ! if the new current field is a ListView

NXTFLD([<New_current_field>] [,<New_current_cell>])! if the new current field is a Grid

When used without parameters, the NxtFld function returns the number of the field containing the cursor from the last INPUT FIELDS, RINPUT FIELDS, INPUT SELECT, or RINPUT SELECT operation. With parameters, NxtFld can be used to record the field (same as the C control attribute) and/or an attribute for the last field.

Comments and Examples

00100 DIM SF$(3)
00110 LET SF$(1)="10,30,c 10,r"
00120 LET SF$(2)="12,30,c 10,r"
00130 LET SF$(3)="14,30,c 10,r"
00140 INPUT FIELDS MAT SF$: A$, B$, C$
00150 PRINT "Cursor ended on FIELD"; NXTFLD
00160 PRINT "Cursor ended on ROW"; NXTROW
00170 PRINT "Cursor ended on COLUMN"; NXTCOL

In the sample program above, the there are three fields available for input. The operator can move the cursor in any direction, but only within these three fields. After the operator hits the <ENTER> key, line 150 will print the number 1, 2 or 3 depending on which field the operator left the cursor on. In addition, line 160 will print the row number (10, 12, or 14) containing the cursor when input was ended. Also, line 130 will print the column number (30 through 39).

NXTFLD provides valuable information when several fields are entered in one statement through an array, specifically, when INPUT FIELDS, RINPUT FIELDS, INPUT SELECT, or RINPUT SELECT is used with an Array.

As NXTFLD returns the subscript in the field definition array of the field containing the cursor from the last INPUT FIELDS, RINPUT FIELDS, INPUT SELECT, or RINPUT SELECT, NXTFLD can be especially useful with the on-line help facility. By using NXTFLD in the HELP$ function in line 990 for the value of the "mark", the operator can be directed to the most relevant portion of the text under the topic HOURS.ENTRY in the help file that explains the valid entries for that field. For example:

00810 INPUT FIELDS MAT FLD$: HRS,OT,DT,SICK HELP 90
00820 STOP
00990 HELP$("HOURS.ENTRY", NXTFLD) : RETRY

FKEY Parameter

NxtFld has been extended to allow an additional numeric parameter, an FKey value, that causes FIELDS and SELECT statements to execute the specified keystroke before requesting operator input. NXTFLD ignores FKEY values of 100 or less and of 114 or greater. The following code uses NXTFLD and FKEY to trap the operator's field exit keystroke and execute it after verifying the data just entered. NOTE that the AE control attributes are used to interrupt execution of the INPUT FIELDS statement upon field exit.

00010 PRINT NEWPAGE
00020 INPUT FIELDS "10,10,C 10,AEU:R;11,10,C10,U": X$,Y$ HELP 41
00030 IF CURFLD=1 THEN PRINT FIELDS "10,22,C": X$
00040 IF FKEY>100 THEN LET NXTFLD(NXTFLD,FKEY) : GOTO 20
00041 PRINT FKEY
00050 STOP

As soon as the operator attempts to exit the first input field, line 30 verifies the entered data by redisplaying it to the right of the field. The CURFLD function in line 40 is then used to reenact the operator's field exit operation: the field just verified is set to the current field, and the operator's attempted exit keystroke (the value of FKEY) is executed. Operator input is then allowed for the next field.

NOTE: If the up arrow was the last key used, the cursor will return to the previous field. If the tab key was used, the cursor will position to the next field with a T (tab stop) attribute.

NOTE that the NXTFLD function in line 40 is executed only if the value of FKEY is greater than 100. Values of 100 or less are ignored, as are interpreted as an attempt to enter the entire screen.

NXTFLD processes field control attributes such as AEP and #. These control attributes are ADDED to the control attributes that are specified for a field. Also, the attributes that are specified with NXTFLD will OVERRIDE (be used instead of) a floating attribute specified with ATTR. The NXTFLD attributes will remain in effect only during the next execution of an INPUT FIELDS or INPUT SELECT statement. Line 20 in the following example uses the X control attribute (see the "X control attribute" discussion in the BRConfig.sys Specifications section for more information).

00010 INPUT FIELDS "10,10,V 10,U;11,10,V 10,U;12,10,V 10,U",attr "HU":X$,Y$,Z$
00020 IF X$="" THEN LET NXTFLD(1,"RX") : GOTO 10
00030 !.. other editing
00040 IF FKEY>100 THEN LET NXTFLD(NXTFLD,FKEY) : GOTO 10
00050 !.. output

If the first field displayed by the above code is left blank, the NXTFLD function in line 20 will reposition the cursor to that field and display it in reverse video. The NXTFLD function's X attribute will additionally cause an auto-enter to occur when the operator attempts to re-exit the field. If the field passes the test on line 20, and the enter key or a function key was not pressed, the field attribute will resume as an underline and the cursor will be positioned at the next field the operator was trying to move to.

ADS expects that line 40 will become a standard line of code in all programs that use input fields and validate data.

Previously, the NxtFld statement supported 3 parameters:

  1. The relative field number.
  2. Optional additional field attributes.
  3. An optional FKEY value to be applied for cursor positioning before processing the INPUT.

In the event the first parameter points to a 2D field/control then instead of the FKEY value, the third (or second numeric) parameter is interpreted as the subscript of the item within the 2D control. For LISTs, this is a row value. For GRIDs this is a Cell Subscript Value. For TOOLBARs, it is the icon subscript value (relative position in toolbar).

Also, in the event the first parameter points to a 2D field/control then the NXTFLD function returns the subscript of the current item within the 2D control.

The NXTFLD system function has been extended to support the current selection upon entry to a multi-field control. The first parameter specifies which field/control is to be affected and the second parameter is the subscript of the cursor upon entry to that control. In the event the first parameter points to a 2D field/control then instead of the FKEY value, the third (or second numeric) parameter is interpreted as the subscript of the item within the 2D control.

  • For LISTviews this is a row value.
  • For GRIDs this is a Cell Subscript Value.
  • For TOOLBARs it is the icon subscript value (relative position in toolbar).

Note that NXTFLD with 2 parameters does not set the initial position of the cursor until the respective control is entered. Also if the mouse is used to enter a control, that will override the specified NXTFLD value.

Option 43 Use old style Input Select with respect to setting CURFLD to the NXTFLD value when a selection is made.


Technical Considerations

CurFld is initialized to -1 at the start of a new program by the RUN command.

Related Functions

CURROW and CURCOL return the row and column numbers of the last INPUT FIELDS, RINPUT FIELDS, INPUT SELECT, or RINPUT SELECT statement.



NXTROW

The NxtRow, Next, and NxtCol internal functions we're introduced in BR! 4.20.

Next, NxtRow and NxtCol

The keyword Next can be used in the same manner as CUR in that the next cursor position within a 2D control can be identified.

00100 INPUT FIELDS "row,col,GRID 10/60, SUB, NEXT, NOWAIT": next_pos

The NxtRow is a internal function that identifies the character position or cell row associated with the next cursor position (e.g. where the mouse was last clicked). If the next cursor position is in a LIST or GRID, then NxtRow specifies the cell clicked within it. If not a 2D control, it specifies the first character position of the next control to receive focus.

NxtCol specifies the column of the respective position.

With respect to these functions, the next cursor position can be the result of keyboard or mouse activity. If the next position results from keyboard activity then NxtRow has the same value as CurRow when Enter is pressed or control was returned in response to a leading attribute such as X (return control upon exit). When the mouse is used to return control to a program, the next cursor position is the pointer location that is double clicked or hot location that is single clicked.

One key concept here is that just as one must keep track of what type of control was last accessed, by means other than CurRow and CurCol, similarly **one must determine the type of control to be next accessed by means other than NxtRow and NxtCol**. This can be done with the system function NxtFld plus hotkey event (fkey) numbers.

CurCol/NxtCol have a slight change in functionality in 4.20 release. Previously they specified the column (relative to the window) of the cursor position. Now they specify the first position of the respective control.

Option 59 has been added to make CurCol (not NxtCol) work the old way.

User_Entry

A leading attribute "^user_entry" returns control to the program upon the cursor entering a field. This does not apply to fields given initial focus by INPUT processing, such as with CURFLD or the first field of a FIELDS operation.

If control is returned to a program because Enter is pressed or in response to the ^user_entry attribute then CURROW has the same value as NXTROW. But when control is returned as a result of the X or AE field attributes CURROW returns the row of the most recent cell or field in focus, and NXTROW returns the row that would be in focus had control not returned to the program. When the mouse is used to return control to a program, the ‘next cursor position’ is the location (row,col) of the cell or control that is double clicked or hot location that is single clicked.



ORD

ORD(<string>)

The Ord internal function returns the ASCII ordinate value (from 0 to 255) of the first character in the string$.

Comments and Examples

ORD("A") is 65 because A is represented by 65 in the ASCII chart.

Related Functions:

Inverse function is Chr$(X).

Technical Considerations

  1. Characters after the first character of the string A$ are ignored.


OS_FILENAME$

The OS_FileName$(A$) internal function does returns the real operating system path of a virtual path. In other words it converts a BR filename A$ based on a Drive statement to the name used by the operating system outside of BR. This internal function does the opposite of BR_FileName$.

In BR a file name that is preceded with a colon (":") (i.e. ":C:\Test") is always interpreted as an operating system file path and/or name. File specifications without a preceding colon will be processed as a BR file path and/or name (a.k.a. Virtual Path)


Syntax

OS_FILENAME$(<path>)
OS_FILENAME$("C:\Example Path\")

Comments and examples

When a DRIVE statement included in the BRCONFIG.SYS file, or executed with EXECUTE CONFIG DRIVE which remaps a location within BR, a system call that refers to a file on the remapped drive will fail unless the remapping parallels the operating system location. Using the OS_FILENAME$(A$) in the system call rather than just the BR name will allow the operating system to find the correct file.

01010 EXECUTE "CONFIG DRIVE X:,\\server1\data\datafiles,\,\"
01020 EXECUTE "SYS COPY "&OS_FILENAME$(X:\tempfile)&" "&OS_FILENAME$(X:\tempfile)&".tmp"

Related functions


PI

PI

The Pi internal function returns the mathematical constant of 3.14159265358979.

Related Functions


PIC$

PIC$[(<currency symbol>)]

The Pic$ internal function by itself returns the current currency symbol. Used with optional 'currency symbol' parameter, it defines a new currency symbol.

Comments and Examples

00010 PRINT "The currency symbol is ";PIC$
00020 PRINT USING 30: 12.34
00030 FORM PIC($$$$.##)
00040 PRINT "The new currency symbol is ";PIC$("#")
00050 PRINT USING 30: 12.34

The output from running the above program, assuming the default for PIC$ was not changed since starting Business Rules, would be:

The currency symbol is $

  $12.34

The new currency symbol is #

  #12.34

Related Functions

For other features especially useful in markets outside the United States, see the INVP parameter of the OPTION statement and the optional format string in the DATE$ and DATE functions.

Technical Considerations

1. After using PIC$(A$) to change the currency symbol, it will stay changed until you exit Business Rules , or until another PIC$(A$) function is executed to change it again.
2. Some European customers may want to include this function in a procedure executed when starting Business Rules.

For example, the command that starts Business Rules could be:

BR "proc start"

and the procedure file START could include:

PIC$("#")
RUN MENU

3. On a multi-user system, changing the currency symbol at one workstation has no effect on other workstations.
4. The string argument A$ must be exactly one character long when the syntax PIC$(A$) is used to change the currency symbol.


POS

POS(<string>,[^]<string>,[[-]<start>])

The Pos internal function returns the position of the first character of a substring in str1$ that matches str2$. Returns 0 if there is no match or str2$ is null.

The optional start parameter specifies the position on which to begin the comparison. When start is positive, the search moves toward the end of the string. When start is negative, the search moves backward toward the beginning of the string.

If str2$ begins with a caret ^, then the ^ is stripped and the search becomes case insensitive. A configuration statement will permit use of a flag character other than ^ (as of 4.2).

Given the (4.2+) POS use of the "^" character, to search for '^' with "let X=POS(string$,'^',5)" you will need to either turn the search character off with CONFIG SEARCH_CHAR OFF or replace the search character with something else as in CONFIG SEARCH_CHAR 7E (where 7E is the hexadecimal representation of an alternate search character).

For disambiguation purposes, see also Pos Parameter.

Comments and Examples

The program below will print the numbers 2, 7, 7 and 7.

00100 LET A$="WXYZ WXYZ"
00200 LET B$="XY"
00300 PRINT POS(A$,B$)              ! find 1st B$
00400 PRINT POS(A$,B$,3)            ! find 1st B$ after position 3
00500 PRINT POS(A$,B$,POS(A$,B$)+1) ! find 2nd B$
00600 PRINT POS(A$,B$,-1)           ! find final B$ (search backwards from the end)

The POS function is often used to determine if a string matches any items listed in a longer string. The crucial information is not the column position of the match, but the zero (when not found) or positive (when found) value returned. The example below illustrates reading a display file one character at a time by using EOL=NONE and dimensioning a variable to be used with LINPUT so that its maximum string length is one. Using POS in line 40, each incoming character is tested to determine which ones are vowels.

00010 DIM X$*1
00020 OPEN #1:"name=datafile,EOL=NONE",DISPLAY,INPUT
00030 LINPUT #1: X$ EOF DONE
00040 IF POS("AaEeIiOoUu",X$) > 0 THEN PRINT X$; " -is a vowel"
00050 GOTO 30
00060 DONE: CLOSE #1:

Related Functions

See also Pos (parameter).


PRINTER_LIST

PRINTER_LIST(<Mat array name>)

The Printer_List internal function returns the number of elements in A$ after redimensioning A$ to the number of active Windows printers. The contents of A$ show the printer names used by Windows, and the default printer is the first element. These names are also suitable OPEN NAME= values to direct output to the respective devices. For example:

10 DIM A$(1)*100
20 LET X=PRINTER_LIST(A$)
30 PRINT MAT A$

This program will display a list of printer names defined on the local machine in the manner the OS 'sees' them.

Also, to make easier use of PRINTER_LIST(A$) returned values, any matching substring of an A$ element will suffice after PRN:/ in the following example:

10 DIM A$(1)*60, SELECTION$*60
20 LET X=PRINTER_LIST(A$)       ! Get Windows Printer List
30 FOR LOOP = 1 TO X
40    A$(LOOP) = A$(LOOP)(1:POS(A$(LOOP),"@")-1) ! Trim device address
50 NEXT LOOP
60 GOSUB USER_SELECT_PRINTER    !  Custom Routine to Select From A$
                                 --- place result into SELECTION$ ---
70 OPEN #255: "Name=PRN:/"& SELECTION$, DISPLAY, OUTPUT

Troubleshooting hint when printing under Windows

From the printers folder, click on the printer that's not working, select properties, details, and spoolsettings. Then make sure the "spool data format" option is set to "RAW," not "EMP".


PROCIN

PROCIN

The ProcIn internal function returns 0 if input is from the screen. Returns 1 if input is from a procedure file.

Comments and Examples

When RUN PROC is used to change programs to accept input from a procedure file instead of the screen, no code changes to the program are required. However, the input from the procedure is not echoed on the screen. The ProcIn variable can be tested in a program to provide this echo if desired.

00010 PRINT "Enter T for totals or D for detail"
00020 LINPUT A$
00030 IF PROCIN=1 THEN PRINT A$


PROGRAM$

PROGRAM$

The Program$ internal function can now be used to return the full name and path (br_filename$)of the currently loaded .br or .wb program. It can be very useful in common error routines.


REC

REC(<file ref>)

The Rec(N) internal function returns the number of the record last processed in file N. For external files, the byte number of the last record processed can also be returned.

For disambiguation purposes, see also Rec Parameter for Read File Statements.

Comments and Examples

If file N is not opened, REC(N) will return -1.

To inform the operator how many records have been processed during the running of a report program, REC(N) and LREC(n) could be used in PRINT FIELDS statements to display a running record counter. The following PRINT statement illustrates the idea:

00540 PRINT "Now reading";REC(N);"of";LREC(N);"records."

Related Functions

For additional information about files, see the following functions:

Technical Considerations

  1. For external files, REC(N) can return either the record number or the byte number, depending on whether the last I/O statement used a REC= clause (the default mode) or a POS= clause (to position to a specified byte number).
  2. The use of REC within an I/O statement is strongly discouraged, especially on multi-user systems. See the Multi-user Programming for additional information.
See also REC= parameter.


REM

REM (Internal Function

RLN

RLN(<file handle>[,<new record length>])

The RLn internal function returns the record length of an open file handle N. The optional X parameter may be used only with external files to reset the record length to the specified amount. The new record length cannot exceed the original record length specified in the OPEN statement.

Comments and Examples

Here are three quick steps to determine the record length of an internal file:

00100 OPEN #1:"name=filename",Internal,Input,Sequential
00200 PRINT RLN(1)
00300 END

The number printed by PRINT RLN(1) is the record length for file 1. The file will be closed when the END statement is processed.

In the following example, RLN shortens the record length of file 1 to 128 bytes.

10 LET RLN(1,128)

See Also

For additional information about external file record lengths, see the POS= and REC= parameters for the READ file statement.

For additional information about files, see the following:


RND

RND[(<numeric expression>)]

The Rnd internal function returns a random number between 0 and 1. The optional numeric parameter can be used to reset the random number generator so that the same random sequence can be generated again later.

Comments and Examples

The short program below will generate 10 random numbers between 0 and 1.

00010 FOR I=1 TO 10
00020   PRINT RND
00030 NEXT I

To rescale the random numbers to be between 1 and 100 and make them integers, change line 20 to:

00020 PRINT INT(RND*100+1)

When the optional parameter is used with the RND function, it resets the random number generator so that the same random sequence can be generated again later. This feature should be added outside the loop so that the numbers produced inside the loop will be different. The following program will produce the same set of numbers each time it is run.

00010 LET X=RND(1)
00020 FOR I=1 TO 10
00030 PRINT RND
00040 NEXT I

Related Functions:

See also the RANDOMIZE statement.


ROUND

ROUND(<numeric expression>,<decimals>)

The Round internal function calculates the value of the first value rounded to the specified number of decimal places.

Comments and Examples

  • ROUND(5.456,2) is 5.46
  • ROUND(5.454,2) is 5.45

Related Functions



RPAD$

 RPAD$(<sring>,<length>[,"character"])

The RPad$ internal function returns the string, adding trailing blanks to make it <length> characters long. If A$ already has at least X characters, no blanks are added.

An optional third parameter ("character") has been added to LPad$ and RPad$ to specify the character to be used for the padding (instead of blanks, which are still the default). The "char" parameter is limited to one character in length (error 410 will result if it is longer). Nulls and Chr$(0) are allowed.

Comments and Examples

To make sure that a string to be used as a key field is long enough to match the length of the key field (assumed to be 12 in this example), the RPad$ function can be used in the KEY= clause.

00510 READ #2,USING 520,KEY=RPAD$(X$,12): COMPANY$ NOKEY 980

A more generalized solution is to use the KLN(2) function to obtain the key length for file 2 instead of coding the 12 as a constant; then the KEY= clause would be KEY=RPAD$(X$,KLN(2)).

See Also


RPT$

RPT$(<string>,<repeat>)

The Rpt$ internal function returns the string, repeated <repeat> times.

Comments and Examples

Line 10 will print a row of stars (asterisks) on the printer that is 132 columns long.

00010 PRINT #255: RPT$("*",132)


RTRM$

RTRM$(<string>[,"character"])

The RTrm$ internal function returns the string, deleting all trailing blanks. So named, because it Right TRiMs the blanks from the string.

An optional second parameter ("character") has been added to LTRM$ and RTRM$ to specify the character to strip (instead of blanks, which are still the default). The "character" parameter is limited to one character in length (error 0410 will result if it is longer). Nulls and CHR$(0) are allowed. The following statement would return the value 12:

PRINT RTRM$("1200","0")

Comments and Examples

RTRM$ can be used to delete extra spaces when formatting an address to CITY, STATE. Line 530 will always allow 18 columns for CITY$ and print the comma in column 19, regardless of the number of non-blank characters in the string. Since RTRM$ is used in line 540, the comma will print immediately after the last non-blank character in CITY$.

00510 READ #2,USING 520: CITY$, STATE$
00520 FORM C 18, C 2
00530 PRINT CITY$;", ";STATE$
00540 PRINT RTRM$(CITY$);", ";STATE$

When the file contains Minneapolis and MN, the output will be:

Minneapolis , MN
Minneapolis, MN

Related Functions

See LTRM$ to trim blanks from the left and LPAD$ and RPAD$ to add blanks.

Technical Considerations

  1. To remove blanks from strings read from a formatted file or screen, V format is an alternative to RTRM$. Reading X$ with V format is equivalent to reading X$ with C format, then doing X$=RTRM$(X$). For example, lines 520 and 540 in the Comments and Examples section above could be changed as follows and still achieve the same results:
00520 FORM V 18, C 2
00540 PRINT CITY$;", ";STATE$


SERIAL

SERIAL

The Serial internal function returns the serial number assigned to this copy of Business Rules!.

Example

00010 print SERIAL

See Also


SESSION$

SESSION$

The Session$ internal function returns WSID$ (three or four digits) and a one digit session identifier number (1-9) to stipulate which among the 9 possible sessions a particular instance of Business Rules! is.

Examples

If you have two sessions of BR open and execute the following command in both of them:

print session$

then the output will most likely be 011 in the first session and 012 in the second.


SETENV

The SetEnv internal function and config are used to set session based environmental variables in Business Rules!.

In a brconfig.sys file you can set a BR environmental variable as follows:

SETENV <field> <value>

In a program you can set a BR environmental variable as follows:

SETENV("<field","<value>") 

The value of either windows environmental variables or BR environmental variables may be accessed in a program or proc by using the Env$ internal function. For example:

Env$("FIELD")


Environment Variable Simulation

The Env$ function, which is used to interrogate the BR environment, has been expanded to permit the simulation of setting an environment variable with configuration statements or with the SETENV system function. As indicated above, either a CONFIG command, or the BRCONFIG.SYS file may set a simulated environment variable:

CONFIG SETENV SIZE '10 x 24'

Also the SETENV system function can do the same thing:

SETENV("SIZE","10 x 24")

This allows a program to use ENV$("SIZE") to retrieve the value '10 x 24', excluding the quotes. In the event SIZE was previously defined in the environment it will be reset to the new value for the duration of the BR session. ENV$ is case insensitive so ENV$("SIZE"), ENV$("SiZe") or ENV$("size") will each produce the same result.

Operating System ENV$ variables cannot be set or altered by CONFIG SETENV.


SPECIAL VARIABLES

Scrn_Size_Posn

SetEnv("SCRN_SIZE_POSN") - case insensitive - will save the current screen size and position for both the new console and the command console, provided they are not minimized to the task bar. The positions of any window that is minimized (graphical window or command console) will not be saved.

As of 4.2, the use of SCRN_SIZE_POSN will also save the operator's insert/overstrike preference.


GUIMode

There is a BR! provided GUIMode environmental variable (case insensitive). It's value is either ON or OFF depending on whether BR is in GUI mode.

x$=env$("GUIMode")

See also:

Env$ GUI Mode


Icon

The Icon environmental variable can be set during the execution of a program by use of SetEnv.

When the special Icon environmental variable is set it will change the icon which the business rules! application displays.

SetEnv("Icon","myicon.ico") sets the icon for the window and the taskbar to the icon specified by the second parameter (e.g. myicon).

00100 SetEnv('Icon','Myicon.ico')


Clipboard

The SetEnv command and the Env$ internal function enable programmatic access to the windows clipboard.

To set the windows clipboard use:

SETENV("CLIPBOARD" ,"<replacement-value>")

To read the windows clipboard use:

ENV$("CLIPBOARD")

These expressions stow and retrieve data to and from the Windows clipboard. The word 'clipboard' is case insensitive.




SGN

SGN(<X>)

The Sgn internal function returns a value which identifies whether a numeric value is negative, positive or zero. The returned values are as follows:

-1 if X is negative

0 if X is zero

1 if X is positve

Example

00010 print SGN(-3)
00020 print SGN(0)
00030 print SGN(6.5)

Output:

-1
0
1

SGN is affected by the value of the BRConfig.sys RD specification. For instance, if RD were set to 6 (the default), the value returned by the following SGN function would be 1 (positive). But if RD were set to 3, the returned value would be 0.


SIN

SIN(<X>)

The Sin internal function is a trigonometric function that returns the sine of X in radians.

Example

00010 print SIN(3.14) ! 3.14 is almost PI, so the result should be almost 0

Output:

0.001593

Related Functions


SLEEP

 SLEEP(<seconds>) 

The Sleep internal function causes the processor to wait the specified number of seconds before continuing execution. It does not tie up the processor while waiting, which is especially important for multi-user systems.

SLEEP now accepts decimal fractions of a second. Resolution accuracy is in milliseconds (up to 3 decimal places). The sleep parameter is still specified in seconds. Some DOS environments have a lower resolution than milliseconds.

Example

00010 let SLEEP(5) ! sleep for 5 seconds


SQR

SQR(<numeric expression>)

The Sqr internal function returns the square root of its argument.

Do not confuse SQR with squaring!

Example

00010 print SQR(4)

Output:

2


SRCH

The Srch internal function searches an array and returns the row number matching the argument. If the argument is not found, then either 0 (BR 4.1 and below) or -1 (BR 4.2 and above). The argument must be the same data type (string or numeric) as the array. The optional "row" parameter defines the starting array element for the search.

SRCH(<array-name>,<argument>[,<row>])

OR

SRCH(<array-name$>,[^]<argument$>[,<row>])

Optional Case Insensitivity and Substring matching

If argument$ begins with the caret ^, then the ^ is stripped and the search for argument$ in array-name$ becomes case insensitive (as of 4.2). Also, when the caret ^ is specified, the search is performed for sub-strings instead of whole strings.

For example:

00010 let a$(1)='abc'
00020 let a$(2)='def'
00030 print srch(mat a$,'^B')

Output:

1

Given the (4.2+) SRCH use of the "^" character, to search for '^' with "let X=POS(string$,'^',5)" you will need to either turn the search character off with CONFIG SEARCH_CHAR OFF or replace the search character with something else as in CONFIG SEARCH_CHAR 7E (where 7E is the hexadecimal representation of an alternate search character).

Comments and Examples

As of 4.2, SRCH returns zero if it fails (instead of -1) unless OPTION BASE ZERO is in effect or OPTION 56 is in effect.

For versions 4.1 and earlier, when the search is unsuccessful, Srch returns -1. Using OPTION BASE 0 will also cause SRCH to return a zero.

In line 510 below, if STATES$ is a string array containing the 50 valid two-letter state abbreviations, then a data entry program could check whether the operator entered a correct abbreviation into the variable ST$ by the following:

500 LINPUT ST$
510 If Srch(Mat States$,ST$) = 0 then goto 500

The example below will find the selected item in a combo box

500 combo_choice$=srch(mat array-name$,"^^")

IMPORTANT

Earlier versions of BR return 0 when SRCH doesn't find the desired argument in the array. Later versions return -1 in the same situation. In order to make you programs produce the same results regardless of the BR version, use the following logic:

00010 if not SRCH(mat array$, string_to_find$) > 0 then
00020    ! add the code for when the result is NOT found
00030 else
00040    ! add the code for when the result IS found
00050 end if

Related Functions

Technical Considerations

  1. If a match was not found, Srch will return -1.


SREP$

 SREP$(<A$>[,<X>],<B$>,<C$>)

The SRep$ internal function or string replace returns A$ with changes. Each substring in A$, from position X on, that matches B$, is replaced by C$. If X is omitted, the search for the match begins at the first character of A$.

Comments and Examples

00010 let A$="Wow, that fish was that big."
00020 let B$="that"
00030 let C$="this"
00040 print SRep$(A$,B$,C$)
00050 print SRep$(A$,7,B$,C$)

The above program will print:

Wow, this fish was this big.
Wow, that fish was this big.

Related Functions


STR$

STR$(<numeric expression>)

The Str$ internal function returns the string form of a numeric value X.

Comments and Examples

00010 LET A = 12.34
00020 LET B = 56.0
00030 LET A$ = STR$(A)
00040 LET B$ = STR$(B)
00050 PRINT A$
00060 PRINT B$
00070 PRINT A$ & B$
00080 PRINT STR$(A+B)

Lines 50 to 80 will print the following four lines:

12.34
56
12.3456
68.34

Related Functions

CNVRT$ converts numbers to strings and provides more formatting options. The inverse function of STR$(X) is VAL(A$). PRINT VAL(STR$(12)) will print the numeric value 12.


STR2MAT

The Str2Mat Internal Function will split a string variable based on a delimiter and place the resulting strings into an array which STR2MAT dynamically re-dimensions. The string to mat and mat to string functions have been extended to ease parsing of CSV and XML data (as of 4.3).

STR2MAT(<string variable>, MAT <array name>, [MAT] <delimiter$>, [<quote-type:trim>])

Parameters

"String Variable" is the variable that contains the data to be converted into an array.

"MAT array-name" is the name of the array into which the variable will be placed.

"Delimiter$" is a string containing the character in the string variable which will be used to separate it into items to be placed in the array. For example, a comma ",". In 4.3 Delimiter can be an array.

"Quotes:Trim" is an optional parameter which handles quotes within the string variable. Quotation marks can suppress the recognition of separators so that any delimiter (such as a comma) that occurs between the specified quotes will not split the data into separate array elements. Quote-type can be Q, QUOTES, ('), or ("), and is case insensitive. Q and QUOTES means that BR will recognize from the data which type of quotes (double or single) will be recognized by examining the first nonblank character. Q and QUOTES also means the enveloping quote characters will be stripped off of the data placed into the receiving array. The trim flags can be :LTRM , :TRIM or :RTRM , and denote post processing of extracted elements. In essence these indicate that leading and/or trailing blanks should be stripped from each resultant array element. The leading colon is only present when quote-type is specified (as of 4.3).

When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (') or ("). If the first character is a quote, then it suppresses the recognition of separators until quotation processing is deactivated by another occurrence of the leading quote. The string is copied until it ends or until an odd number of successive occurrences of the governing quote type is encountered. During this processing, two adjacent occurrences of the governing quote character denote a single embedded occurrence of the quote character and is disregarded as a quote deactivator.

Defaults

Actually, the delimiter parameter is also optional in a sense. But practically speaking it is mandatory.

The default delimiter searches for the following combinations of line feed and carriage return characters:

This enables multiple CSV rows to be contained in a single string.

Further Explanation

1. When more than one occurrence of the same delimiters are used next to each other, BR honors all of them making an empty string element in the resulting array for all but the first occurrence of the delimiter. Consider the following example:

00010 let namelist$="Mary,John,,Salomi,Thomas,,,David,Sonia"
00020 str2mat(namelist$,mat customer$,",")
00030 print mat customer$

Output:

Mary
John

Salomi
Thomas


David
Sonia

Customer$(3), Customer$(6), and Customer$(7) would have a value of "".

2. If the delimiter is "", every character will be put in a separate element of the array.

3. Str2Mat performs the opposite action of Mat2Str

4. Str2Mat dynamically redimensions the array (mat customer$ in the above example) as needed to include all of the items from the source string variable. It returns the number in the final array.

5. When the delimiter is an array, both will signify the start of a new element in the final array. But when two consecutive delimiters are different, they will not create a blank element in the array. For example:

dim namelist$*256,customer$(7),delim$(2)
let namelist$="Mary,Jo.hn,,.Salomi.Thomas,,,David,,.Sonia"
let delim$(1)=","
let delim$(2)="."
str2mat(namelist$,mat customer$,Mat delim$)
print mat customer$

will return:

To restate this: when elements of a delimiter array occur adjacent to each other within the source string, they are grouped as one separator substring. When the same occur consecutively, it creates a null element in the final array output.

CSV Parsing Example (4.3)

The following code spinet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through the records.

01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1,CSV_HEADER$*999,CSV_FIELDS$(1)*40,CSV_DATA$(1)*60
01020    form C," "
01040    let CSV_FILE$="Sample_File.tab" : let TAB$=CHR$(9)
01060    open #(CSV_HANDLE:=10): "name="&CSV_FILE$&",shr",display,input 
01080    linput #CSV_HANDLE: CSV_HEADER$
01100    let CSV_DELIM$=TAB$
01120    if POS(CSV_HEADER$,TAB$) <= 0 then 
01140       let CSV_DELIM$=","
01160    end if 
01180    let STR2MAT(CSV_HEADER$,MAT CSV_FIELDS$,CSV_DELIM$,"QUOTES:TRIM")
01200    print using 1020: MAT CSV_FIELDS$
01220    do 
01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv
01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,"Q:trim")
01280       print using 1020: MAT CSV_DATA$
01300    loop 
01320 Exit_Csv: !

You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.

XML Parsing Enhancements

STR2MAT may also be used to Parse XML data.

This powerful tool is a bit more complex than parsing CSV files, but useful nonetheless.

The following example will parse XML$ into "MAT XML_LINE$"

 10 DIM XML$*999999,XML_LINE$(1)*32000
 20 XML$="<XML><NODE><ITEM>ITEM VALUE</ITEM></NODE></XML>"
 100 LET Str2mat(XML$,Mat XML_LINE$,">","TRIM")

This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data

Data:

 <XML>
  <NODE>
    <ITEM>ITEM VALUE</ITEM>
  </NODE>
 </XML>

Results:

 <XML
 <NODE
 <ITEM
 ITEM VALUE</ITEM
 </NODE
 </XML

If the node names are known, a more complete and useful technique can be performed. You may use an array of Delimiter$ values to parse the data. Take the following example:

100    dim XML$*999999,XML_LINE$(1)*32000,DELIM$(4)*32
110    let XML$="<XML><NODE><ITEM>ITEM VALUE</ITEM><ITEM2>ITEM2 VALUE</ITEM2></NODE></XML>"
120    read MAT SEP$
130    data </XML>,</NODE>,</ITEM>,</ITEM2>
140    let STR2MAT(XML$,MAT XML_LINE$,MAT DELIM$,"TRIM")
150    print MAT XML_LINE$

This program would return the following results:

 <XML><NODE><ITEM>ITEM VALUE
 <ITEM2>ITEM2 VALUE

Notice that "Nested Nodes" are listed before the initial data, this may be used to identify the node.

Quote Processing Examples

The following chart demonstrates how data in the source string is handled if * and , are delimiters:

String Final Array Element Explanation
*"abc,def" abc,def the comma is not recognized as a separator and is part of the data since it is within quotes.
*abc"def abc"def embedded quotes may occur anywhere within a string after the first character
*"abc"def" abcdef" quotation processing is deactivated by the center quote mark
*"abcdef" abcdef normal data
*"abc'def" abc'def the single quote is treated like any other character while double quotes govern
*'abc"def' abc"def double quotes are treated like any other character while single quotes govern
*"abc""def" abc"def pairs of governing quotes denote a single embedded quote
*"abc"""def" abc"def" the third successive occurrence deactivates quote processing

Reading a CSV file

The following program takes this CSV file and uses STR2MAT to store the information in two separate arrays.

! This Sample Program Reads A Csv and puts it into two arrays, which could easily be written into a BR data file.
   dim Wholepiece$*10000, codelist$(1)*256, description$(1)*256, code$(1), nextline$*256

   open #1: "name=hcodeexport.csv, recl=500",display,input

   mat Code$(0)
   mat Description$(0)
   let delim$=","

   do while file(1)=0
      linput #1: nextline$ eof ignore
      if file(1)=0 then
         ! at this point we have 1 line of the CSV file in NextLine$
         let str2mat(nextline$,mat codelist$,delim$,"Q:trim")
 
         ! at this point we have mat CodeList$ sized 2 with each element in it
 
         ! lets do something useful, lets build them together into 2 arrays
         index=udim(mat code$) +1 ! find new position in the arrays
         mat Code$(index)         ! Make the arrays bigger
         mat Description$(index)
 
         ! Put the stuff we found into the new arrays
         let code$(index)=codelist$(1)
         let description$(index)=codelist$(2)
      end if
   loop
 
 ! print mat code$
 ! print mat description$
  for i=1 to 15
     print code$(i)&" "&description$(i)
  next i
   
  close #1:

Final Sample Program

The following program demonstrates quote processing and trimming, using both STR2MAT and MAT2STR:

00010 ! Rep Str2mat
00020    dim LINE$*400,DESC$(5)*30,SEP$(1)*20,QTYPE$(2)*20
00030 ! 
00040    print NEWPAGE
00050    let LINE$='"  TEST1",, " TEST,,3","TEST4" ,,"TE""S""T6 "'
00060    print LINE$;TAB(1);"no augmentation or quote recognition"
00070    print "note column 3 gets split up and quotes are data"
00080    let STR2MAT(LINE$,MAT DESC$,',')
00090    let MAT2STR(MAT DESC$,LINE$,',')
00100    for X = 1 to UDIM(DESC$) !:
            print DESC$(X), LEN(DESC$(X)) !:
         next X !:
         print LINE$
00110    linput Z$
00120 ! 
00130    print LINE$;TAB(1);"strip quotes and trim outside the quotes"
00140    print "convert commas to tildes"
00150    let STR2MAT(LINE$,MAT DESC$,',',"Q:TRIM")
00160    let MAT2STR(MAT DESC$,LINE$,'~')
00170    for X = 1 to UDIM(DESC$) !:
            print DESC$(X), LEN(DESC$(X)) !:
         next X !:
         print LINE$
00180    linput Z$
00190 ! 
00200    let LINE$='"  TEST1",, " TEST,,3","TEST4" ,,"TE""S""T6 "'
00210    print LINE$;TAB(1);"strip quotes and notrim"
00220    print "convert commas to tildes"
00230    print "column 3 is broken up because the leading quote is embedded without trim"
00240    let STR2MAT(LINE$,MAT DESC$,',',"Q")
00250    let MAT2STR(MAT DESC$,LINE$,'~')
00260    for X = 1 to UDIM(DESC$) !:
            print DESC$(X), LEN(DESC$(X)) !:
         next X !:
         print LINE$


SUM

SUM(<numeric array>)

The Sum internal function returns the sum of all the elements in the numeric array named.

SUM also works with multi-dimensional matrices.

Comments and Examples

00010 DIM X(8)
00020 DATA 2,5,3,4,6,3,4,5
00030 READ MAT X
00040 PRINT SUM(X)

Line 40 will print 32, which is the total of the elements of array X.

Related

See Also

Sort Control File Parameter SUM


TAB

(For the GUI interface, see also Tabs).

TAB(<col>)

The TAB(x) internal function positions the cursor at column x (similar to POS in a FORM statement), where x is any numeric expression. If the current position of the line is greater than column x, the cursor is positioned at column x in the next line. If x is negative, TAB(1) is assumed. If x is not an integer, it is rounded. If x is greater than the record length, the cursor is positioned at column 1 in the next line.

Comments and Examples

00010 PRINT TAB(3)

Line 10 positions the cursor on the screen at position 3.

Related Functions

Other special functions used mainly in PRINT are BELL and NEWPAGE.

Technical Considerations

  1. In an unformatted PRINT statement, when NEWPAGE precedes the TAB(X) function, the TAB function will appear to be off by one column because the character for NEWPAGE appears in the output buffer, but not on the screen or printer. Avoid using NEWPAGE (or BELL) before TAB in an unformatted PRINT statement. One remedy is to use one PRINT statement for NEWPAGE (and BELL) and another for the TAB function and other output.


TAN

TAN(<x>)

The Tan internal function is a mathematical trigonometric function that calculates the tangent of X in radians.

Example

00010 print TAN(PI/2) ! in mathematics, TAN(PI/2) = infinity, output should be a very large number

Output:

6.189863256179240E+14

See Also


TIME$

TIME$

The Time$ internal function returns the system time in the format hh:mm:ss.

Comments and Examples

00010 PRINT #255,USING 20: TIME$, DATE$
00020 FORM "Time: ",C 8,SKIP 1," Date: ",C 8

Lines 10 and 20 illustrate putting TIME$ and DATE$ as identifying information on a printed report.

See Also

Technical Considerations

  1. The time can be changed by the operator using the Time command from Business Rules!. On a multi-user system, these changes do not affect other workstations.


TIMER

TIMER

The Timer internal function returns a "Real Number" with 5 decimal digits accuracy with the number of seconds elapsed since midnight, January 1, 1970.

  • This starting point is obtained from the operating system so it is only as accurate as your system time.

This value is used internally by the pro filer to monitor performance, but may be used within programs to measure the time very accurately

The function works as far back as 4.1x.

Simple Example:

PRINT TIMER
Returns:  1305192990.17052

The following example shows the timer value, and converts it to various units "Minutes" "Hours" "Years". It also shows the total time elapsed for this program. (It usually returns 0.0156004) With 1 Attempt.

00001   PRINT Newpage
00010   LET Tot_Time=Timer
00020   PRINT "Timer:",Tot_Time
00030   PRINT "Minutes:",Int(Tot_Time/60)
00040   PRINT "Hours:",Int(Tot_Time/(60*60))
00050   PRINT "Years:",(Tot_Time/(60*60*24*365))
00060   LET New_Time=Timer
00065   IF (New_Time-Tot_Time)=0 THEN LET Attempts+=1 : GOTO 60
00070   PRINT "Time Elapsed: (";Attempts+1;")",New_Time-Tot_Time



TRIM$

TRIM$(<string>[,"<character>"])

The Trim$ internal function can be used to delete both leading and trailing blanks from the string A$. Trim$(A$) returns the same value as RTrm$(LTrm$(A$)). The optional "char" parameter can be used to specify the character (instead of blanks) to strip; this parameter is limited to one character in length. Nulls (Chr$(0)) are allowed.

Example

00010 print trim$("     The leading blanks will be removed. So will the trailing ones      ")&"..."
00020 print trim$("*****The leading  stars will be removed. So will the trailing ones******","*")

Output:

The leading blanks will be removed. So will the trailing ones... 
The leading  stars will be removed. So will the trailing ones

See also


UDIM

UDIM(<array name> [,<dimension>])


The UDim(A$,X) internal function returns the number of rows in the array if X=1. Returns the number of columns in the array if X=2. Returns the current size of dimensions 3, 4, 5, 6 or 7 when X is 3, 4, 5, 6 or 7. If the optional parameter X is omitted, UDIM returns the size of the first dimension.

Comments and Examples

00010 DIM A(15,20)
00020 PRINT UDIM(A), UDIM(A,1), UDIM(A,2)
00030 FOR I = 1 TO UDIM(A)
00040  FOR J = 1 TO UDIM(A,2)
00050   LET A(I,J) = I + J
00060  NEXT I
00070 NEXT J

The three numbers printed in line 20 will be 15, 15 and 20. Notice that by using UDIM in lines 30 and 40 this program can be changed to use a different sized two-dimensional array; the only programming change would be to change the dimensions in line 10 (or the array could be redimensioned using the MAT statement).

The following example increases the size of array arr$ by one element:

00010 mat arr$(udim(arr$)+1)

Related Functions

Other functions that operate on arrays are:

AIdx

DIdx

Srch

Sum



UNHEX$

UNHEX$(<string>)

The UnHex$ internal function converts A$ to hexadecimal representation.

Comments and Examples

The following example shows the relationship between HEX$ and UNHEX$:

00010 print UNHEX$("+") ! the hexadecimal value which represents the "+" character
00020 print  HEX$("2B") ! the character represented by the hexadecimal value "2B"

Output:

2B
+

UnHex$ can be used to examine the packed decimal representation (PD format) of a number written to an internal or external file.

00010 OPEN #1: "name=billtest,replace,recl=4",INTERNAL,OUTIN,RELATIVE
00020 WRITE #1,USING 30,REC=1:4.56,-4.56
00030 FORM 2*PD 2.2
00040 READ #1,USING 50,REC=1:A$,B$
00050 FORM 2*C 2
00060 REREAD #1,USING 30:A,B
00070 PRINT STR$(A)&" in PD 2.2 format is  - "&UNHEX$(A$)
00080 PRINT STR$(B)&" in PD 2.2 format is  - "&UNHEX$(B$)

The above program will print the following:

4.56 in PD 2.2 format is  - 456F
-4.56 in PD 2.2 format is  - 456D

See the KStat$ function for another example of using UnHex$.

Related Functions

Inverse function is Hex$.


UPRC$

UPRC$(<string>)

The Uprc$ internal function converts any lowercase letters in the string A$ to uppercase letters.

Comments and Examples

00010 LET A$ = "Business Rules "
00020 PRINT UPRC$(A$)

Line 20 will print: BUSINESS RULES

Related Functions

See the LwrC$ function for conversion from uppercase to lowercase.

Technical Considerations

  1. Another method for conversion to uppercase is the CU, VU and GU format specifications, which are effective only with INPUT FIELDS and RINPUT FIELDS. This method converts keystrokes, as they are being entered, into uppercase only. See also the CL Format Specification, VL Format Specification and GL Format Specification format specifications for more information about converting incoming keystrokes to lowercase.


USERID$

USERID$

The UserID$ internal function returns the BR licensee name. See also WBVersion$ and serial.

Example

If the name of your company to which BR is licensed is XYZ Company, then the output of the following example

00010 print userid$

will be

XYZ Company


VAL

VAL(<string>)

The Val(A$) internal function returns A$ expressed as a numeric value rather than a string.

Comments and Examples

00010 LET A$ = "12"
00020 LET B$ = "34"
00030 PRINT VAL(A$)+VAL(B$)

Line 30 will print the number 46.

Related Functions

The inverse function of VAL(A$) is STR$(X). PRINT STR$(VAL("12")) will print the string value "12" without the quotation marks.

Technical Considerations

  1. The string in A$ can contain only spaces, digits, a plus sign, a minus sign, and a period; any other characters will generate a conversion error. These conversion errors can be trapped with the CONV error condition.


VARIABLE$

VARIABLE$

The Variable$ internal function returns the name of the variable that failed in the last I/O statement. Besides being invaluable for debugging, Variable$ can be used as a topic to call Help$. Note: VARIABLE$ will not be set if the error results from the field specification (error numbers 850 through 890). Also, if the field is a calculation such as A+B, Variable$ will not be set.

Example

00010 input a,b,c

If at the command line the user types in

4,5,x

then BR will give an error 726, because "x" is not an acceptable value for the variable c.

If after getting the error, you type in variable$ at the command prompt, the result will be:

c


VERSION

VERSION(<file number>[,<numeric expression>])

The Version internal function returns the currently marked version number for a BR internal file. With an optional second parameter, VERSION can be used to set this version number in the file, provided the file has been opened for OUTPUT.

Version can also be set when creating a file by specifying VERSION= on the Open Internal string expression.

Related Functions


WBPLATFORM$

WBPLATFORM

WBVERSION$

The WBVersion$ internal function returns a string representing the running version of BR.

WBVERSION$


See Also



WSID$

WSID$ and WSID return a two or three digit Workstation ID. On multi-user systems, this variable is helpful in keeping separate the files and printouts from different workstations, as is Session$.

Comments and Examples

00010 PRINT #255,USING 20: WSID$, DATE$
00020 FORM "workstation: ",C 2," Date: ",C 8

Lines 10 and 20 illustrate putting WSID$ and DATE$ as identifying information on a printed report.

Technical Considerations

  1. workstation IDs can also be accessed through another notation for use in file names. This alternate notation is [WSID] and is often easier to use in procedures.
  2. For example, FREE WORK[WSID]. It is also useful in OPEN statements.
  3. WSID$ can only be set when BR32.exe is launched, by use of a command line parameter or (more commonly) a WSID specification in BRConfig.sys.


XLATE$

The Xlate$ internal function returns a string translated using a second string as a translation table. If a position is specified, it starts at that position of the first string; otherwise it starts at the first character.

XLATE$(<string>,<translation string>[,<position>])

Comments and Examples

XLATE$(A$,B$,X)

Whenever ASCII character null (CHR$(0)) is found in A$, it is replaced by the first character in B$. ASCII character Ctrl-A (CHR$(1)) is replaced by the second character in B$. In other words, ASCII character N-1 is replaced by the Nth character of B$. ASCII values greater than LEN(B$)-1 are not changed.

00100 LET Y$=XLATE$(X$,TABLE$)

In line 100, Y$ will be a translation of X$ using Table$. For example, spaces (ASCII value 32) will be replaced by Table$(33:33), the character in the 33rd position of Table$.

UTF-8 / UTF8 Support

If the first 7 bytes of the table consists of STR2UTF or UTF2STR (case insensitive) then conversion to or from UTF-8 takes place.

XLATE$(A$,"str2utf") ! converts A$ to UTF-8

Related Functions

During input or output operations, data can be translated (for example from ASCII to EBCDIC) by using the TRANSLATE= parameter in the OPEN statement.