<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://brwiki2.brulescorp.com/brwiki2/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mikhail.zheleznov</id>
	<title>BR Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://brwiki2.brulescorp.com/brwiki2/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Mikhail.zheleznov"/>
	<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Special:Contributions/Mikhail.zheleznov"/>
	<updated>2026-04-16T14:11:25Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11311</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11311"/>
		<updated>2020-07-25T17:15:15Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: corrected sample code error&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
&lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.&lt;br /&gt;
&lt;br /&gt;
DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
# Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
# Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
## Verify that data has not changed.&lt;br /&gt;
## Verifying that two files are the same.&lt;br /&gt;
## Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  [https://en.wikipedia.org/wiki/OpenSSL Wikipedia] explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
&lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
&lt;br /&gt;
 openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
*Easy to use&lt;br /&gt;
*Compatible with Windows Vista/7&lt;br /&gt;
*Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
*Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
*Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
Other improvements:&lt;br /&gt;
*Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
*Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
*The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide.&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
*Native Courier New  1.6 	- available in PCL&lt;br /&gt;
*Native Letter Gothic  2.0	- available in PCL&lt;br /&gt;
*Stretched Fonts 2.6		- NWP and PDF only&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
 10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
&lt;br /&gt;
01100 ! &lt;br /&gt;
&lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
&lt;br /&gt;
01160 ! &lt;br /&gt;
&lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
&lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 01160    print MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11310</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11310"/>
		<updated>2020-07-25T17:13:02Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
&lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.&lt;br /&gt;
&lt;br /&gt;
DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
# Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
# Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
## Verify that data has not changed.&lt;br /&gt;
## Verifying that two files are the same.&lt;br /&gt;
## Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  [https://en.wikipedia.org/wiki/OpenSSL Wikipedia] explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
&lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
&lt;br /&gt;
 openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
*Easy to use&lt;br /&gt;
*Compatible with Windows Vista/7&lt;br /&gt;
*Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
*Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
*Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
Other improvements:&lt;br /&gt;
*Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
*Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
*The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide.&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
*Native Courier New  1.6 	- available in PCL&lt;br /&gt;
*Native Letter Gothic  2.0	- available in PCL&lt;br /&gt;
*Stretched Fonts 2.6		- NWP and PDF only&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
 10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
&lt;br /&gt;
01100 ! &lt;br /&gt;
&lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
&lt;br /&gt;
01160 ! &lt;br /&gt;
&lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
&lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11309</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11309"/>
		<updated>2020-07-25T17:12:09Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
&lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.&lt;br /&gt;
&lt;br /&gt;
DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
# Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
# Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
## Verify that data has not changed.&lt;br /&gt;
## Verifying that two files are the same.&lt;br /&gt;
## Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  [https://en.wikipedia.org/wiki/OpenSSL Wikipedia] explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
&lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
&lt;br /&gt;
 openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
*Easy to use&lt;br /&gt;
*Compatible with Windows Vista/7&lt;br /&gt;
*Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
*Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
*Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
Other improvements:&lt;br /&gt;
*Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
*Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
*The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide.&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
*Native Courier New  1.6 	- available in PCL&lt;br /&gt;
*Native Letter Gothic  2.0	- available in PCL&lt;br /&gt;
*Stretched Fonts 2.6		- NWP and PDF only&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
 10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
&lt;br /&gt;
01100 ! &lt;br /&gt;
&lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
&lt;br /&gt;
01160 ! &lt;br /&gt;
&lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
&lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11308</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11308"/>
		<updated>2020-07-25T17:10:48Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
&lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.&lt;br /&gt;
&lt;br /&gt;
DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
# Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
# Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
## Verify that data has not changed.&lt;br /&gt;
## Verifying that two files are the same.&lt;br /&gt;
## Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  [https://en.wikipedia.org/wiki/OpenSSL Wikipedia] explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
&lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
&lt;br /&gt;
 openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
*Easy to use&lt;br /&gt;
*Compatible with Windows Vista/7&lt;br /&gt;
*Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
*Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
*Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
Other improvements:&lt;br /&gt;
*Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
*Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
*The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide.&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
*Native Courier New  1.6 	- available in PCL&lt;br /&gt;
*Native Letter Gothic  2.0	- available in PCL&lt;br /&gt;
*Stretched Fonts 2.6		- NWP and PDF only&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
 10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11307</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11307"/>
		<updated>2020-07-25T17:09:23Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
&lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.&lt;br /&gt;
&lt;br /&gt;
DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
# Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
# Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
## Verify that data has not changed.&lt;br /&gt;
## Verifying that two files are the same.&lt;br /&gt;
## Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  [https://en.wikipedia.org/wiki/OpenSSL Wikipedia] explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
&lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
&lt;br /&gt;
 openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
*Easy to use&lt;br /&gt;
*Compatible with Windows Vista/7&lt;br /&gt;
*Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
*Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
*Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
Other improvements:&lt;br /&gt;
*Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
*Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
*The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide.&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
*Native Courier New  1.6 	- available in PCL&lt;br /&gt;
*Native Letter Gothic  2.0	- available in PCL&lt;br /&gt;
*Stretched Fonts 2.6		- NWP and PDF only&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11306</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11306"/>
		<updated>2020-07-25T17:05:50Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
&lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.&lt;br /&gt;
&lt;br /&gt;
DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
# Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
# Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
## Verify that data has not changed.&lt;br /&gt;
## Verifying that two files are the same.&lt;br /&gt;
## Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  [https://en.wikipedia.org/wiki/OpenSSL Wikipedia] explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
&lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
&lt;br /&gt;
 openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
*Easy to use&lt;br /&gt;
*Compatible with Windows Vista/7&lt;br /&gt;
*Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
*Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
*Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
Other improvements:&lt;br /&gt;
*Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
*Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
*The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide.&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11305</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11305"/>
		<updated>2020-07-25T17:00:32Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
&lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.&lt;br /&gt;
&lt;br /&gt;
DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
# Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
# Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
## Verify that data has not changed.&lt;br /&gt;
## Verifying that two files are the same.&lt;br /&gt;
## Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  [https://en.wikipedia.org/wiki/OpenSSL Wikipedia] explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
&lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
&lt;br /&gt;
 openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11304</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11304"/>
		<updated>2020-07-25T16:58:28Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
&lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.&lt;br /&gt;
&lt;br /&gt;
DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
# Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
# Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
## Verify that data has not changed.&lt;br /&gt;
## Verifying that two files are the same.&lt;br /&gt;
## Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  [https://en.wikipedia.org/wiki/OpenSSL Wikipedia] explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
&lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
 ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11303</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11303"/>
		<updated>2020-07-25T16:57:48Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
&lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.&lt;br /&gt;
&lt;br /&gt;
DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
# Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
# Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
## Verify that data has not changed.&lt;br /&gt;
## Verifying that two files are the same.&lt;br /&gt;
## Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  [https://en.wikipedia.org/wiki/OpenSSL Wikipedia] explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
&lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11302</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11302"/>
		<updated>2020-07-25T16:56:55Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: added newlines for readibility&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
&lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.&lt;br /&gt;
&lt;br /&gt;
DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
# Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
# Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
## Verify that data has not changed.&lt;br /&gt;
## Verifying that two files are the same.&lt;br /&gt;
## Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  [https://en.wikipedia.org/wiki/OpenSSL Wikipedia] explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
&lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11301</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11301"/>
		<updated>2020-07-25T16:55:38Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: added openssl link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
&lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.&lt;br /&gt;
&lt;br /&gt;
DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
# Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
# Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
## Verify that data has not changed.&lt;br /&gt;
## Verifying that two files are the same.&lt;br /&gt;
## Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  [https://en.wikipedia.org/wiki/OpenSSL Wikipedia] explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Option_(config)&amp;diff=11300</id>
		<title>Option (config)</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Option_(config)&amp;diff=11300"/>
		<updated>2020-07-25T16:50:52Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: added missing option 66 description&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;See also [[Option (disambiguation)]].&lt;br /&gt;
&lt;br /&gt;
These are some of the &#039;&#039;&#039;Options&#039;&#039;&#039; you can use in the [[BRConfig.sys]] file.  Most may also be enabled by use of a &#039;&#039;[[Config]] Option&#039;&#039; statement.  Most can be disabled with a &#039;&#039;Config Option [number] Off&#039;&#039; statement.&lt;br /&gt;
&lt;br /&gt;
These can be used within a BR program, for example:&lt;br /&gt;
&lt;br /&gt;
 00010 Execute &amp;quot;Config Option 1&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Or can be set at the time of [[System Startup|BR32.exe launch]] by a line being placed in [[BRConfig.sys]] like:&lt;br /&gt;
&lt;br /&gt;
 Option 37&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; cellpadding=2 cellspacing=0 align=center&lt;br /&gt;
!Option&lt;br /&gt;
!Description&lt;br /&gt;
!Supports&amp;lt;br&amp;gt;Config Option X Off&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;INVP&#039;&#039;&#039;||Normal input of commas and periods is interchanged in PIC, N, NZ, L, G and GZ format specifications to support European- style numbers. (From [[INPUT FIELDS]])&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;1&#039;&#039;&#039;||FORM A*C 10, default to 1 if A&amp;lt;1&lt;br /&gt;
|Yes ([[4.18]]+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;2&#039;&#039;&#039;||keyboard values less than 0x20 not ignored&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;3&#039;&#039;&#039;||set print flags&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;4&#039;&#039;&#039;||pads to record length for display out if EOL=NONE&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;5&#039;&#039;&#039;||default to [[ISAM]] (index type 4). The normal default is [[BTREE]] (index type 7)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;6&#039;&#039;&#039;||keep path=0 defaults to change to path when exiting BR same as when entered, as in UNIX&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;7&#039;&#039;&#039;||use old style syntax checking of IF statements&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;8&#039;&#039;&#039;||use old style loop counter for keyboard - 2nd Option on break&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;11&#039;&#039;&#039;||don&#039;t clear unreferenced variable&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;13&#039;&#039;&#039;||sets the number of milli-seconds for scancodes wait e.g Option 13 200 (this number can be incremented by 20 till it reaches 400)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;14&#039;&#039;&#039;||allow multiple locks on same record from duplicate opens, for same file opened twice at same station&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;15&#039;&#039;&#039;||suppress indentation of comment continuation&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;16&#039;&#039;&#039;||omit display of loaded file name&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;17&#039;&#039;&#039;||don&#039;t consolidate [[4205]] error codes&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;18&#039;&#039;&#039;||BR ignores any century value - where century is omitted from the date&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;19&#039;&#039;&#039;||subtract one from dates after 2/2000 for SCO pre version 5&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;21&#039;&#039;&#039;||make date$(0) yield 12/31/1899&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;22&#039;&#039;&#039;||The system will automatically create new indexes in BTREE2 format and will keep track of which files utilize BTREE2 indexes. It will audit and if needed rebuild&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;23&#039;&#039;&#039;||make [[IOERR]]s not move file pointer forward to next record. BR will advance the record pointer when a successful read I/O operation occurs, even when a [[CONV]] (conversion) error takes place during the read operation. This Option lets the IOERR exit condition occur only when the record pointer is not advanced&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;24&#039;&#039;&#039;||disable X attributes during SELECT. Prior to BR version [[3.9]], this Option had a different meaning. Originally, Option 24 specified that a file should be freed and recreated when opened REPLACE to avoid a NOVELL failure to truncate the file. But BR *now* automatically truncates. If it can&#039;t for some reason, THEN it will remove the file and recreate it. Effective with BR 3.9+, Option 24 suppresses the recognition of the &amp;quot;X&amp;quot; attribute during INPUT SELECT operations. BR versions prior to 3.9 operated this way by default - without the Option - even though the documentation indicated that X applies to SELECT operations.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;25&#039;&#039;&#039;||make file$(0) be CON: (if in Windows)&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;26&#039;&#039;&#039;||suppresses the creation of [[.BAK]] files during Replace&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;27&#039;&#039;&#039;||Ignore Invalid Y2K Key Data (err [[4120]])&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;28&#039;&#039;&#039;||Force all CONFIG PRINTER statements to specify a printer.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;29&#039;&#039;&#039;||Save programs as .WB files. (Default is .BR)&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;30&#039;&#039;&#039;||server side printing for client-server.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;31&#039;&#039;&#039;||suppress [[native windows printing]]; treat WIN:/ as direct printing&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;32&#039;&#039;&#039;||Supress notification of error [[6245]], which indicates an invalid or unsupported (by BR) escape sequence has been printed during [[Native Windows Printing]].&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;33&#039;&#039;&#039;||( 30  31  32  64 ) (default is 31) [[Record locking]] for large file support. The problem addressed by this Option was that BR doesn&#039;t actually lock records, but locks a byte corresponding to each record in a zone way beyond the actual file. The filespace doesn&#039;t really have to exist to allow locking. This permits [[ODBC]] and other report writers to access locked records. BR also uses this zone to arbitrate the types of Open allowed. With BR 3.9, some file sizes were growing into the zone, and records were being locked inadvertently.&lt;br /&gt;
*Option 33 30           1GB maximum bytes in a data file.&lt;br /&gt;
*Option 33 31           (The default 2GB limit)&lt;br /&gt;
*Option 33 32           (4GB Limit)&lt;br /&gt;
*Option 33 64           Turns on 64 bit locking&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;34&#039;&#039;&#039;||sends print screen images to PRN:/10 instead of PRN:/SELECT.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;35&#039;&#039;&#039;||Honor keepalive timeout (no longer available)&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;36&#039;&#039;&#039;||Enables the cursor during [[INPUT SELECT]] This Option is needed for some hand held scanners that do not have the ability to display in reverse image.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;37&#039;&#039;&#039;||With versions [[4.14]]+, BR returns: [[FKEY]] value of 116 when exiting a field with right arrow.&lt;br /&gt;
&lt;br /&gt;
With OPTION 37 on BR returns an FKEY value of 104 which is the same as the down arrow. This (104) is how BR worked previously.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;38&#039;&#039;&#039;||This suppresses an error caused by specification of an N in the trailing attribute position. This Option is provided only for legacy purposes.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;39&#039;&#039;&#039;||Suppresses the automatic right alignment of labels ending with a colon.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;40&#039;&#039;&#039;||Show hot text as buttons by default. Normally hot text does not appear as a button unless the fkey value is preceded with a B. This Option can be selectively overridden by preceding the fkey value with an H.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;41&#039;&#039;&#039;||Ignore GUI statements when they are encountered in non-GUI mode.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;42&#039;&#039;&#039;||Suppress automatic drive mapping during Windows shell calls.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;43&#039;&#039;&#039;|| INPUT SELECT changes fields before returning control; use old style Input Select with respect to setting [[CURFLD]] to the [[NXTFLD]] value when a selection is made.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;44&#039;&#039;&#039;||Make the mouse wheel produce the same result as the arrow keys when control is returned to a program via the E, L or X field attributes. Without this Option, the mouse wheel returns Fkey results of 124/125 (up arrow/down arrow). With this Option it returns 102/104 during INPUT FIELDS and 105/106 during INPUT SELECT operations (normal arrow key responses). Note: Option 44 is NOT needed to use the mouse wheel. It only pertains to Fkey results with E, X or L.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;45&#039;&#039;&#039;|| Allows the old method of extended field specification in addition to the new method.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;46&#039;&#039;&#039;||Normalizes numpad + and - keys. This removes Field Plus / Minus special processing, which is no longer needed with Datahilite field clearing.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;47&#039;&#039;&#039;||Enable the continued use of PRINTER= in OPEN statements.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;48&#039;&#039;&#039;||&#039;&#039;&#039;Note- OPTION 48 functionality was changed in version [[4.2]].&#039;&#039;&#039;&lt;br /&gt;
If OPTION 48 is not specified, ENTER will return an FKEY value of zero and a double-click will return any FKEY value assigned to the field. &lt;br /&gt;
Use OPTION 48 only to have the ENTER key return any FKEY value assigned to the field.&lt;br /&gt;
|Yes (4.2+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;49&#039;&#039;&#039;||Use relative path for spool file name passed in [[SPOOLCMD]].&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;50&#039;&#039;&#039;||Suppress theme usage for text controls. This enables the Windows classical look under XP.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;51&#039;&#039;&#039;||Reuse deleted records for all files.  This is an old unpublished and untested Option for re-use deleted records during WRITE operations.  Deleted records will be RE-USED, and then lost permanently.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;52&#039;&#039;&#039;||Enable the second click of a double click operation to produce its own interrupt with [[FKey]] value 201.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;53&#039;&#039;&#039;||Allow mouse positioning inside a field other than the current field.  Without this Option clicking anywhere in a non-current active input field will process it as though the field were entered via the arrow keys.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;54&#039;&#039;&#039;||Exit BR! at any console command prompt with a message box showing program name and line number:clause.  Waiting for input by a program has no affect.&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;55&#039;&#039;&#039;||Some fixed width fonts have characters that aren&#039;t exactly the same width as the other characters. This can present column alignment problems. This option slows down printing slightly, but positions each character individually instead of streaming the data to the printer and letting the the data self align. &lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;56&#039;&#039;&#039;||[[Srch]] return -1 instead of 0 when no match is found.&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;57&#039;&#039;&#039;|| Clear Fkeys of inactive Q combo box fields.&lt;br /&gt;
|Yes (4.18+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;58&#039;&#039;&#039;||On FnKey has been disabled in 4.20+ (use [[On FKey]] instead), however this option restores recognition of [[FnKey]] .&lt;br /&gt;
|Yes ([[4.20]]+)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;59&#039;&#039;&#039;||Make [[CurCol]] (not [[NxtCol]]) work the old way: use cursor position instead of field start for CURROW/COL&lt;br /&gt;
|???&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;60&#039;&#039;&#039;||allows 4.2 to edit and save programs while maintaining 4.18 compatible formatting so that 4.18 can still run those programs.  If this is used you may not utilize 4.2 features.&lt;br /&gt;
|NO&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;61&#039;&#039;&#039;||Do not Map a Drive if not explicitly defined by DRIVE statements [[BRConfig.sys]]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;62&#039;&#039;&#039;||Use Draw Line Border Specification (Otherwise report error!).&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;63&#039;&#039;&#039;|| Allow INPUT SELECT to input data; [[INPUT SELECT]] &amp;quot;Reads Data&amp;quot;, We should use [[INPUT FIELDS]] W=with ^LABEL instead!&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;64&#039;&#039;&#039;|| 15 Allows max network delay for passing data to client.&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;65&#039;&#039;&#039;||Ignore ON ATTN statements.&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;66&#039;&#039;&#039;||The secret key to be used for encryption.&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;67&#039;&#039;&#039;||Data Hilite on every INPUT FIELDS statement.&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;68&#039;&#039;&#039;||Prevent stretching printed fonts.&lt;br /&gt;
|Yes&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;69&#039;&#039;&#039;||ignore file closing errors during end or chain&lt;br /&gt;
|Yes?&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;70&#039;&#039;&#039;||&lt;br /&gt;
* Same as Option 54 (exits on any command console prompt) but allows [[Relaxed]] parameter to allow for some debugging.&lt;br /&gt;
* [[4.32]]+ ON SOFLOW IGNORE overrides line error handlers as in previous versions&lt;br /&gt;
|* Yes and Relaxed ([[4.30]]+)&lt;br /&gt;
* [[4.32]]+ Yes?&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;71&#039;&#039;&#039;|| Prevent [[auto complete]] for editable [[combo boxes]] (added in 4.32 ish)&lt;br /&gt;
| Yes?&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;72&#039;&#039;&#039;|| Prevent auto complete for [[select]] combo boxes. (added in 4.32 ish)&lt;br /&gt;
| Yes?&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;73&#039;&#039;&#039;|| Treat IGNORE as a label reference for line level error handlers&lt;br /&gt;
| Yes?&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;74&#039;&#039;&#039;|| Adds the [[WSID]] to the temporary [[edit]] file names. (added in 4.3)&lt;br /&gt;
| Yes&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|&#039;&#039;&#039;97&#039;&#039;&#039;||set network retries per second (default is 5)&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;98&#039;&#039;&#039;||turn OFF check for all NULL in read / writes&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;99&#039;&#039;&#039;||turn ON check for all NULL in read / writes&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Config]]&lt;br /&gt;
[[Category:Miscellaneous Statements]]&lt;br /&gt;
[[Category:Statements]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11299</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11299"/>
		<updated>2020-07-25T16:46:41Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: changed hard coded numbers to # and ##, as indentation didn&amp;#039;t work properly otherwise&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
&lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.&lt;br /&gt;
&lt;br /&gt;
DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
# Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
# Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
## Verify that data has not changed.&lt;br /&gt;
## Verifying that two files are the same.&lt;br /&gt;
## Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11298</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11298"/>
		<updated>2020-07-25T16:40:41Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: added newlines for readibility&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
&lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.&lt;br /&gt;
&lt;br /&gt;
DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11297</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11297"/>
		<updated>2020-07-25T16:39:09Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: added newlines for readibility&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
&lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=BRListenerInstaller.exe&amp;diff=11292</id>
		<title>BRListenerInstaller.exe</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=BRListenerInstaller.exe&amp;diff=11292"/>
		<updated>2020-07-08T20:22:03Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: Corrected the paths for listener and config file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;Install.exe&#039;&#039;&#039; file is used to install [[Client Server]] versions of [[Business Rules!]].&lt;br /&gt;
&lt;br /&gt;
Install.exe may be found as part of the [[418g_winsvr.zip]] found on [http://www.brulescorp.com/brules/download.html]&lt;br /&gt;
&lt;br /&gt;
This is the [[BRListener.exe]] Installer for [[NT Server]] (can be found at the bottom of [br_version]_WinSvr.zip on the web site download section ([http://www.brulescorp.com/brules/download.html])) &lt;br /&gt;
&lt;br /&gt;
This program is used to launch the [[BRListener.exe]] process as a service.  BRListener.exe must be in [[C:\Windows\System32]] and [[BRListener.conf]] must be configured and located in [[C:\Windows]].&lt;br /&gt;
&lt;br /&gt;
The /Release parameter can be used, like:&lt;br /&gt;
&lt;br /&gt;
 Install /Release&lt;br /&gt;
&lt;br /&gt;
to stop the BRListener.exe process.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Client Server]]&lt;br /&gt;
[[Category:Files]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11291</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11291"/>
		<updated>2020-06-27T16:15:25Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: Added and corrected descriptions, improved formating&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
The following are examples of SQL connection strings which can be placed inside of brconfig.sys file or executed dynamically from BR command line:&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ] [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
&lt;br /&gt;
? indicates a login or password prompt&lt;br /&gt;
&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE db-ref CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)};DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb;Uid=Admin;Pwd=abcd1234&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The following will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
 CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
&lt;br /&gt;
Here are 2 methods of opening an SQL connection and execute a query in BR: &lt;br /&gt;
&lt;br /&gt;
 1) OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
 2) OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
&lt;br /&gt;
In method 2, filename refers to a DISPLAY file containing an SQL statement that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11290</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11290"/>
		<updated>2020-06-27T15:44:20Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: Removed &amp;quot;new world&amp;quot; phrase, as SQL support is not new&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11288</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11288"/>
		<updated>2020-05-31T15:34:13Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: fixed formatting, added text sample&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy.&lt;br /&gt;
&lt;br /&gt;
To run the next code sample, first save the folowing text in a file named Sample_File.tab in your BR directory. &lt;br /&gt;
&lt;br /&gt;
 First, Last, Age, City&lt;br /&gt;
 &amp;quot;Stas&amp;quot;, &amp;quot;Kalban&amp;quot;, 99, &amp;quot;Las Vegas&amp;quot;&lt;br /&gt;
 &amp;quot;Mike&amp;quot;, &amp;quot;Dugas&amp;quot;,98, &amp;quot;Buenos Buenos&amp;quot;&lt;br /&gt;
 &amp;quot;John&amp;quot;, &amp;quot;Bubon&amp;quot;, 96, &amp;quot;Hong Kong&amp;quot;&lt;br /&gt;
&lt;br /&gt;
This code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records:&lt;br /&gt;
&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
Alternatively, you could use any other valid CSV data, as long as the input file is named Sample_File.tab&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11287</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11287"/>
		<updated>2020-05-31T15:01:02Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039; &#039; &#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11286</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11286"/>
		<updated>2020-05-31T14:51:10Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: fixed links, added description of STR2MAT and MAT2STR&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[STR2MAT]] and [[MAT2STR]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT function splits a string into an array.&lt;br /&gt;
&lt;br /&gt;
MAT2STR function joins an array into a string.&lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11285</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11285"/>
		<updated>2020-05-31T14:46:52Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
&lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11284</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11284"/>
		<updated>2020-05-31T14:43:27Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
 &amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
 &amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
 &amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
 &amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
 &#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
 &amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
&lt;br /&gt;
Examples&lt;br /&gt;
&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
 abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
 abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
 abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
 abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
 &#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
 abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
 &#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
 &amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11283</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11283"/>
		<updated>2020-05-31T14:36:50Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
&lt;br /&gt;
Standard BR Quote Processing:&lt;br /&gt;
&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11282</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11282"/>
		<updated>2020-05-31T14:30:18Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: Created missing section heading for Logging&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ==&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11275</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11275"/>
		<updated>2020-05-17T17:03:37Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: Included Logging page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
{{:Logging}}&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11274</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11274"/>
		<updated>2020-05-17T16:56:10Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;: (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 ! create and populate a LIST control &lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11273</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11273"/>
		<updated>2020-05-17T16:54:21Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11272</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11272"/>
		<updated>2020-05-17T16:53:43Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11271</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11271"/>
		<updated>2020-05-17T16:52:26Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11270</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11270"/>
		<updated>2020-05-17T16:51:09Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: Formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
&#039;&#039;&#039;SEL&#039;&#039;&#039; - Read one or more selected items.&lt;br /&gt;
&#039;&#039;&#039;SELONE&#039;&#039;&#039; - Select only one item.&lt;br /&gt;
&#039;&#039;&#039;ALL&#039;&#039;&#039; - Read all items in the control (except headings).&lt;br /&gt;
&#039;&#039;&#039;CUR&#039;&#039;&#039; - Current cell or row number.&lt;br /&gt;
&#039;&#039;&#039;CHG&#039;&#039;&#039; - All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
&#039;&#039;&#039;RANGE&#039;&#039;&#039; - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
&#039;&#039;&#039;CELL_RANGE&#039;&#039;&#039; – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
&lt;br /&gt;
Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
&lt;br /&gt;
Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
&lt;br /&gt;
Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
&lt;br /&gt;
Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11269</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11269"/>
		<updated>2020-05-17T16:44:51Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$, MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; - The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11268</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11268"/>
		<updated>2020-05-17T16:43:03Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
In [[list and grid]] controls, arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11267</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11267"/>
		<updated>2020-05-17T16:30:45Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11266</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11266"/>
		<updated>2020-05-17T16:29:59Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039; The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039; Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039; Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039; The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039; The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039; Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;HEADERS&#039;&#039;&#039; The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COLCNT&#039;&#039;&#039; The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SORT_ORDER&#039;&#039;&#039; would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11265</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11265"/>
		<updated>2020-05-17T16:26:13Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039;	 - The number of cells specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039;	 - Read the Cell Subscript Values.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039;	 - Read each cell specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039;     - The number of rows specified.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039;     - The subscripts of the specified rows.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039;	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
HEADERS  – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
SORT_ORDER - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11264</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11264"/>
		<updated>2020-05-17T16:25:04Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CNT&#039;&#039;&#039;	 - The number of cells specified.&lt;br /&gt;
&#039;&#039;&#039;SUB&#039;&#039;&#039;	 - Read the Cell Subscript Values.&lt;br /&gt;
&#039;&#039;&#039;CELL&#039;&#039;&#039;	 - Read each cell specified.&lt;br /&gt;
&#039;&#039;&#039;ROWCNT&#039;&#039;&#039;     - The number of rows specified.&lt;br /&gt;
&#039;&#039;&#039;ROWSUB&#039;&#039;&#039;     - The subscripts of the specified rows.&lt;br /&gt;
&#039;&#039;&#039;ROW&#039;&#039;&#039;	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
HEADERS  – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
SORT_ORDER - Provides a value of zero for each unsorted column and gives the ascending sequence of column sorts that have occurred. If a column has been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
 column 1 (descending most rescent)&lt;br /&gt;
 column 2 (ascending first sorted)&lt;br /&gt;
 column 3 (not sorted)&lt;br /&gt;
 column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return&lt;br /&gt;
 array(1) -&amp;gt;  -1&lt;br /&gt;
 array(2) -&amp;gt;   3&lt;br /&gt;
 array(3) -&amp;gt;   0&lt;br /&gt;
 array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11263</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11263"/>
		<updated>2020-05-17T16:21:53Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
CNT	 - The number of cells specified.&lt;br /&gt;
SUB	 - Read the Cell Subscript Values.&lt;br /&gt;
CELL	 - Read each cell specified.&lt;br /&gt;
ROWCNT   - The number of rows specified.&lt;br /&gt;
ROWSUB   - The subscripts of the specified rows.&lt;br /&gt;
ROW	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
HEADERS  – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
(MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
SORT_ORDER - Provides a value of zero for each unsorted column and gives&lt;br /&gt;
the ascending sequence of column sorts that have occurred. If a column has&lt;br /&gt;
been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
column 1 (descending most rescent)&lt;br /&gt;
column 2 (ascending first sorted)&lt;br /&gt;
column 3 (not sorted)&lt;br /&gt;
column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return-&lt;br /&gt;
array(1) -&amp;gt;  -1&lt;br /&gt;
array(2) -&amp;gt;   3&lt;br /&gt;
array(3) -&amp;gt;   0&lt;br /&gt;
array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11262</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11262"/>
		<updated>2020-05-17T16:20:06Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
&lt;br /&gt;
CNT	 - The number of cells specified.&lt;br /&gt;
SUB	 - Read the Cell Subscript Values.&lt;br /&gt;
CELL	 - Read each cell specified.&lt;br /&gt;
ROWCNT   - The number of rows specified.&lt;br /&gt;
ROWSUB   - The subscripts of the specified rows.&lt;br /&gt;
ROW	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
HEADERS  – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
                                   (MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
SORT_ORDER - Provides a value of zero for each unsorted column and gives&lt;br /&gt;
the ascending sequence of column sorts that have occurred. If a column has&lt;br /&gt;
been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
column 1 (descending most rescent)&lt;br /&gt;
column 2 (ascending first sorted)&lt;br /&gt;
column 3 (not sorted)&lt;br /&gt;
column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return-&lt;br /&gt;
array(1) -&amp;gt;  -1&lt;br /&gt;
array(2) -&amp;gt;   3&lt;br /&gt;
array(3) -&amp;gt;   0&lt;br /&gt;
array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11261</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11261"/>
		<updated>2020-05-17T16:15:31Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. &lt;br /&gt;
&lt;br /&gt;
Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
  CNT	 - The number of cells specified.&lt;br /&gt;
  SUB	 - Read the Cell Subscript Values.&lt;br /&gt;
  CELL	 - Read each cell specified.&lt;br /&gt;
  ROWCNT - The number of rows specified.&lt;br /&gt;
  ROWSUB - The subscripts of the specified rows.&lt;br /&gt;
  ROW	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
 HEADERS – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
                                   (MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
  COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
  SORT_ORDER - Provides a value of zero for each unsorted column and gives&lt;br /&gt;
the ascending sequence of column sorts that have occurred. If a column has&lt;br /&gt;
been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
column 1 (descending most rescent)&lt;br /&gt;
column 2 (ascending first sorted)&lt;br /&gt;
column 3 (not sorted)&lt;br /&gt;
column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return-&lt;br /&gt;
array(1) -&amp;gt;  -1&lt;br /&gt;
array(2) -&amp;gt;   3&lt;br /&gt;
array(3) -&amp;gt;   0&lt;br /&gt;
array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11260</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11260"/>
		<updated>2020-05-17T16:13:50Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: Moved better example description from BR 4.3 release notes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
Example where all arrays are one dimensional and may have the incorrect number of elements:&lt;br /&gt;
   &lt;br /&gt;
 INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
  CNT	 - The number of cells specified.&lt;br /&gt;
  SUB	 - Read the Cell Subscript Values.&lt;br /&gt;
  CELL	 - Read each cell specified.&lt;br /&gt;
  ROWCNT - The number of rows specified.&lt;br /&gt;
  ROWSUB - The subscripts of the specified rows.&lt;br /&gt;
  ROW	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
 HEADERS – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
                                   (MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
  COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
  SORT_ORDER - Provides a value of zero for each unsorted column and gives&lt;br /&gt;
the ascending sequence of column sorts that have occurred. If a column has&lt;br /&gt;
been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
column 1 (descending most rescent)&lt;br /&gt;
column 2 (ascending first sorted)&lt;br /&gt;
column 3 (not sorted)&lt;br /&gt;
column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return-&lt;br /&gt;
array(1) -&amp;gt;  -1&lt;br /&gt;
array(2) -&amp;gt;   3&lt;br /&gt;
array(3) -&amp;gt;   0&lt;br /&gt;
array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11259</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11259"/>
		<updated>2020-05-17T16:11:19Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: Formatting changes for better readability&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
===ON error-type IGNORE=== &lt;br /&gt;
ON error-type IGNORE now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
===For client / server configurations===&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
===CHR$(6)=== &lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
===MAT2STR and STR2MAT===&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
===STATUS USERS===&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
===BRERR$===&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples:&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
===ODBC===&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
e.g.   &lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
  CNT	 - The number of cells specified.&lt;br /&gt;
  SUB	 - Read the Cell Subscript Values.&lt;br /&gt;
  CELL	 - Read each cell specified.&lt;br /&gt;
  ROWCNT - The number of rows specified.&lt;br /&gt;
  ROWSUB - The subscripts of the specified rows.&lt;br /&gt;
  ROW	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
 HEADERS – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
                                   (MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
  COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
  SORT_ORDER - Provides a value of zero for each unsorted column and gives&lt;br /&gt;
the ascending sequence of column sorts that have occurred. If a column has&lt;br /&gt;
been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
column 1 (descending most rescent)&lt;br /&gt;
column 2 (ascending first sorted)&lt;br /&gt;
column 3 (not sorted)&lt;br /&gt;
column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return-&lt;br /&gt;
array(1) -&amp;gt;  -1&lt;br /&gt;
array(2) -&amp;gt;   3&lt;br /&gt;
array(3) -&amp;gt;   0&lt;br /&gt;
array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11258</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11258"/>
		<updated>2020-05-13T16:04:09Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: Fixed Model Tree&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
“ON error-type IGNORE” now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
For client / server configurations:&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples-&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
e.g.   &lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
  CNT	 - The number of cells specified.&lt;br /&gt;
  SUB	 - Read the Cell Subscript Values.&lt;br /&gt;
  CELL	 - Read each cell specified.&lt;br /&gt;
  ROWCNT - The number of rows specified.&lt;br /&gt;
  ROWSUB - The subscripts of the specified rows.&lt;br /&gt;
  ROW	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
 HEADERS – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
                                   (MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
  COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
  SORT_ORDER - Provides a value of zero for each unsorted column and gives&lt;br /&gt;
the ascending sequence of column sorts that have occurred. If a column has&lt;br /&gt;
been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
column 1 (descending most rescent)&lt;br /&gt;
column 2 (ascending first sorted)&lt;br /&gt;
column 3 (not sorted)&lt;br /&gt;
column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return-&lt;br /&gt;
array(1) -&amp;gt;  -1&lt;br /&gt;
array(2) -&amp;gt;   3&lt;br /&gt;
array(3) -&amp;gt;   0&lt;br /&gt;
array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
** Server executable&lt;br /&gt;
** Workstation Client dll&lt;br /&gt;
** Linux Terminal Support&lt;br /&gt;
** Linux Client dll ( .so )&lt;br /&gt;
&lt;br /&gt;
* Client Server Model&lt;br /&gt;
** On Client Machine-&lt;br /&gt;
*** Client executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
** On Server&lt;br /&gt;
*** Server executable&lt;br /&gt;
*** Workstation Client dll&lt;br /&gt;
*** BR Listener installed&lt;br /&gt;
*** [ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11257</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11257"/>
		<updated>2020-05-13T16:00:03Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
“ON error-type IGNORE” now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
For client / server configurations:&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples-&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
e.g.   &lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
  CNT	 - The number of cells specified.&lt;br /&gt;
  SUB	 - Read the Cell Subscript Values.&lt;br /&gt;
  CELL	 - Read each cell specified.&lt;br /&gt;
  ROWCNT - The number of rows specified.&lt;br /&gt;
  ROWSUB - The subscripts of the specified rows.&lt;br /&gt;
  ROW	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
 HEADERS – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
                                   (MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
  COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
  SORT_ORDER - Provides a value of zero for each unsorted column and gives&lt;br /&gt;
the ascending sequence of column sorts that have occurred. If a column has&lt;br /&gt;
been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
column 1 (descending most rescent)&lt;br /&gt;
column 2 (ascending first sorted)&lt;br /&gt;
column 3 (not sorted)&lt;br /&gt;
column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return-&lt;br /&gt;
array(1) -&amp;gt;  -1&lt;br /&gt;
array(2) -&amp;gt;   3&lt;br /&gt;
array(3) -&amp;gt;   0&lt;br /&gt;
array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
*[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
*[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
*[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
*[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
*[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
* Server executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* Linux Terminal Support&lt;br /&gt;
* Server executable&lt;br /&gt;
* Linux Client dll ( .so )&lt;br /&gt;
* Client Server Model&lt;br /&gt;
* On Client Machine-&lt;br /&gt;
* Client executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* On Server&lt;br /&gt;
* Server executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* BR Listener installed&lt;br /&gt;
[ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
&lt;br /&gt;
=== Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in C:\BR\MYAPP\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
 SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
Example:&lt;br /&gt;
 C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11256</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11256"/>
		<updated>2020-05-13T15:54:46Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
“ON error-type IGNORE” now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
For client / server configurations:&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples-&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
e.g.   &lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
  CNT	 - The number of cells specified.&lt;br /&gt;
  SUB	 - Read the Cell Subscript Values.&lt;br /&gt;
  CELL	 - Read each cell specified.&lt;br /&gt;
  ROWCNT - The number of rows specified.&lt;br /&gt;
  ROWSUB - The subscripts of the specified rows.&lt;br /&gt;
  ROW	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
 HEADERS – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
                                   (MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
  COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
  SORT_ORDER - Provides a value of zero for each unsorted column and gives&lt;br /&gt;
the ascending sequence of column sorts that have occurred. If a column has&lt;br /&gt;
been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
column 1 (descending most rescent)&lt;br /&gt;
column 2 (ascending first sorted)&lt;br /&gt;
column 3 (not sorted)&lt;br /&gt;
column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return-&lt;br /&gt;
array(1) -&amp;gt;  -1&lt;br /&gt;
array(2) -&amp;gt;   3&lt;br /&gt;
array(3) -&amp;gt;   0&lt;br /&gt;
array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
 100 ! create and populate a GRID&lt;br /&gt;
 150 ! Reading subscripts does not reset the CHG flags in the control&lt;br /&gt;
 200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
 205 ! BR redimensions the receiving arrays as needed. Reading the data also resets the CHG flags in the control.&lt;br /&gt;
 210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
 220 ! process the changed rows now present in the data arrays --&lt;br /&gt;
 300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs, MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
* Server executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* Linux Terminal Support&lt;br /&gt;
* Server executable&lt;br /&gt;
* Linux Client dll ( .so )&lt;br /&gt;
* Client Server Model&lt;br /&gt;
* On Client Machine-&lt;br /&gt;
* Client executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* On Server&lt;br /&gt;
* Server executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* BR Listener installed&lt;br /&gt;
[ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
===) Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
e.g.	DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in:&lt;br /&gt;
C:\BR\SPOOL\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
  e.g.   SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
e.g.		C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11255</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11255"/>
		<updated>2020-05-13T15:52:19Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
“ON error-type IGNORE” now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
For client / server configurations:&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples-&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
e.g.   &lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
  CNT	 - The number of cells specified.&lt;br /&gt;
  SUB	 - Read the Cell Subscript Values.&lt;br /&gt;
  CELL	 - Read each cell specified.&lt;br /&gt;
  ROWCNT - The number of rows specified.&lt;br /&gt;
  ROWSUB - The subscripts of the specified rows.&lt;br /&gt;
  ROW	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
 HEADERS – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
                                   (MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
  COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
  SORT_ORDER - Provides a value of zero for each unsorted column and gives&lt;br /&gt;
the ascending sequence of column sorts that have occurred. If a column has&lt;br /&gt;
been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
column 1 (descending most rescent)&lt;br /&gt;
column 2 (ascending first sorted)&lt;br /&gt;
column 3 (not sorted)&lt;br /&gt;
column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return-&lt;br /&gt;
array(1) -&amp;gt;  -1&lt;br /&gt;
array(2) -&amp;gt;   3&lt;br /&gt;
array(3) -&amp;gt;   0&lt;br /&gt;
array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
OR&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
  100 -- create and populate a GRID --&lt;br /&gt;
  ........&lt;br /&gt;
  200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
         (Reading subscripts does not reset the CHG flags in the control.)&lt;br /&gt;
  210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$,&lt;br /&gt;
                                  MAT Data2, MAT Data3$ )&lt;br /&gt;
          BR redimensions the receiving arrays as needed.&lt;br /&gt;
         (Reading the data also resets the CHG flags in the control.)&lt;br /&gt;
&lt;br /&gt;
  220 -- process the changed rows now present in the data arrays --&lt;br /&gt;
  ........&lt;br /&gt;
  300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs,&lt;br /&gt;
                   MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
* Server executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* Linux Terminal Support&lt;br /&gt;
* Server executable&lt;br /&gt;
* Linux Client dll ( .so )&lt;br /&gt;
* Client Server Model&lt;br /&gt;
* On Client Machine-&lt;br /&gt;
* Client executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* On Server&lt;br /&gt;
* Server executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* BR Listener installed&lt;br /&gt;
[ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
===) Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
e.g.	DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in:&lt;br /&gt;
C:\BR\SPOOL\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
  e.g.   SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
e.g.		C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11254</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11254"/>
		<updated>2020-05-13T15:46:43Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
“ON error-type IGNORE” now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
For client / server configurations:&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples-&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
e.g.   &lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
  CNT	 - The number of cells specified.&lt;br /&gt;
  SUB	 - Read the Cell Subscript Values.&lt;br /&gt;
  CELL	 - Read each cell specified.&lt;br /&gt;
  ROWCNT - The number of rows specified.&lt;br /&gt;
  ROWSUB - The subscripts of the specified rows.&lt;br /&gt;
  ROW	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
 HEADERS – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
                                   (MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
  COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
  SORT_ORDER - Provides a value of zero for each unsorted column and gives&lt;br /&gt;
the ascending sequence of column sorts that have occurred. If a column has&lt;br /&gt;
been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
column 1 (descending most rescent)&lt;br /&gt;
column 2 (ascending first sorted)&lt;br /&gt;
column 3 (not sorted)&lt;br /&gt;
column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return-&lt;br /&gt;
array(1) -&amp;gt;  -1&lt;br /&gt;
array(2) -&amp;gt;   3&lt;br /&gt;
array(3) -&amp;gt;   0&lt;br /&gt;
array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
 Result- Nine rows replace five, and the total content of the control is expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
 Result- Five rows are deleted, and the total size of the control is reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
 Start=7, end=0 (anything less than 7), and the arrays are DIMed to support three rows&lt;br /&gt;
 Result- Three rows are inserted ahead of row seven and the total content of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
 Start=5000, end={any value}, the control only has 482 rows, and the source arrays are DIMed to support eleven rows&lt;br /&gt;
 Result- Eleven rows are appended to the end of the control and become rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$,&lt;br /&gt;
                                          MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
                                - or -&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
  100 -- create and populate a GRID --&lt;br /&gt;
  ........&lt;br /&gt;
  200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
         (Reading subscripts does not reset the CHG flags in the control.)&lt;br /&gt;
  210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$,&lt;br /&gt;
                                  MAT Data2, MAT Data3$ )&lt;br /&gt;
          BR redimensions the receiving arrays as needed.&lt;br /&gt;
         (Reading the data also resets the CHG flags in the control.)&lt;br /&gt;
&lt;br /&gt;
  220 -- process the changed rows now present in the data arrays --&lt;br /&gt;
  ........&lt;br /&gt;
  300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs,&lt;br /&gt;
                   MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
* Server executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* Linux Terminal Support&lt;br /&gt;
* Server executable&lt;br /&gt;
* Linux Client dll ( .so )&lt;br /&gt;
* Client Server Model&lt;br /&gt;
* On Client Machine-&lt;br /&gt;
* Client executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* On Server&lt;br /&gt;
* Server executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* BR Listener installed&lt;br /&gt;
[ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
===) Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
e.g.	DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in:&lt;br /&gt;
C:\BR\SPOOL\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
  e.g.   SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
e.g.		C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11253</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11253"/>
		<updated>2020-05-13T15:44:36Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
“ON error-type IGNORE” now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
For client / server configurations:&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples-&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
e.g.   &lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
  CNT	 - The number of cells specified.&lt;br /&gt;
  SUB	 - Read the Cell Subscript Values.&lt;br /&gt;
  CELL	 - Read each cell specified.&lt;br /&gt;
  ROWCNT - The number of rows specified.&lt;br /&gt;
  ROWSUB - The subscripts of the specified rows.&lt;br /&gt;
  ROW	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
 HEADERS – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
                                   (MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
  COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
  SORT_ORDER - Provides a value of zero for each unsorted column and gives&lt;br /&gt;
the ascending sequence of column sorts that have occurred. If a column has&lt;br /&gt;
been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
column 1 (descending most rescent)&lt;br /&gt;
column 2 (ascending first sorted)&lt;br /&gt;
column 3 (not sorted)&lt;br /&gt;
column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return-&lt;br /&gt;
array(1) -&amp;gt;  -1&lt;br /&gt;
array(2) -&amp;gt;   3&lt;br /&gt;
array(3) -&amp;gt;   0&lt;br /&gt;
array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$, MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples- Using the following statement various scenarios are described.&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$,&lt;br /&gt;
                                          MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
  Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
  Result- Nine rows replace five, and the total content of the control is&lt;br /&gt;
          expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
  Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
  Result- Five rows are deleted, and the total size of the control is&lt;br /&gt;
          reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
  Start=7, end=0 (anything less than 7), and the arrays are DIMed to&lt;br /&gt;
           support three rows&lt;br /&gt;
  Result- Three rows are inserted ahead of row seven and the total content&lt;br /&gt;
          of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
  Start=5000, end={any value}, the control only has 482 rows, and the source&lt;br /&gt;
          arrays are DIMed to support eleven rows&lt;br /&gt;
  Result- Eleven rows are appended to the end of the control and become&lt;br /&gt;
          rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$,&lt;br /&gt;
                                          MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
                                - or -&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
  100 -- create and populate a GRID --&lt;br /&gt;
  ........&lt;br /&gt;
  200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
         (Reading subscripts does not reset the CHG flags in the control.)&lt;br /&gt;
  210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$,&lt;br /&gt;
                                  MAT Data2, MAT Data3$ )&lt;br /&gt;
          BR redimensions the receiving arrays as needed.&lt;br /&gt;
         (Reading the data also resets the CHG flags in the control.)&lt;br /&gt;
&lt;br /&gt;
  220 -- process the changed rows now present in the data arrays --&lt;br /&gt;
  ........&lt;br /&gt;
  300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs,&lt;br /&gt;
                   MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
* Server executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* Linux Terminal Support&lt;br /&gt;
* Server executable&lt;br /&gt;
* Linux Client dll ( .so )&lt;br /&gt;
* Client Server Model&lt;br /&gt;
* On Client Machine-&lt;br /&gt;
* Client executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* On Server&lt;br /&gt;
* Server executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* BR Listener installed&lt;br /&gt;
[ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
===) Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
e.g.	DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in:&lt;br /&gt;
C:\BR\SPOOL\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
  e.g.   SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
e.g.		C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11252</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11252"/>
		<updated>2020-05-13T15:43:04Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: formatting&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
“ON error-type IGNORE” now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
For client / server configurations:&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples-&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
e.g.   &lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
  CNT	 - The number of cells specified.&lt;br /&gt;
  SUB	 - Read the Cell Subscript Values.&lt;br /&gt;
  CELL	 - Read each cell specified.&lt;br /&gt;
  ROWCNT - The number of rows specified.&lt;br /&gt;
  ROWSUB - The subscripts of the specified rows.&lt;br /&gt;
  ROW	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
 HEADERS – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
                                   (MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
  COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
  SORT_ORDER - Provides a value of zero for each unsorted column and gives&lt;br /&gt;
the ascending sequence of column sorts that have occurred. If a column has&lt;br /&gt;
been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
column 1 (descending most rescent)&lt;br /&gt;
column 2 (ascending first sorted)&lt;br /&gt;
column 3 (not sorted)&lt;br /&gt;
column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return-&lt;br /&gt;
array(1) -&amp;gt;  -1&lt;br /&gt;
array(2) -&amp;gt;   3&lt;br /&gt;
array(3) -&amp;gt;   0&lt;br /&gt;
array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot;:             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
 INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot;: MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START, MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
4c) Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$,&lt;br /&gt;
                                          MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples- Using the following statement various scenarios are described.&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$,&lt;br /&gt;
                                          MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
  Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
  Result- Nine rows replace five, and the total content of the control is&lt;br /&gt;
          expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
  Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
  Result- Five rows are deleted, and the total size of the control is&lt;br /&gt;
          reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
  Start=7, end=0 (anything less than 7), and the arrays are DIMed to&lt;br /&gt;
           support three rows&lt;br /&gt;
  Result- Three rows are inserted ahead of row seven and the total content&lt;br /&gt;
          of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
  Start=5000, end={any value}, the control only has 482 rows, and the source&lt;br /&gt;
          arrays are DIMed to support eleven rows&lt;br /&gt;
  Result- Eleven rows are appended to the end of the control and become&lt;br /&gt;
          rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$,&lt;br /&gt;
                                          MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
                                - or -&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
  100 -- create and populate a GRID --&lt;br /&gt;
  ........&lt;br /&gt;
  200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
         (Reading subscripts does not reset the CHG flags in the control.)&lt;br /&gt;
  210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$,&lt;br /&gt;
                                  MAT Data2, MAT Data3$ )&lt;br /&gt;
          BR redimensions the receiving arrays as needed.&lt;br /&gt;
         (Reading the data also resets the CHG flags in the control.)&lt;br /&gt;
&lt;br /&gt;
  220 -- process the changed rows now present in the data arrays --&lt;br /&gt;
  ........&lt;br /&gt;
  300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs,&lt;br /&gt;
                   MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
* Server executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* Linux Terminal Support&lt;br /&gt;
* Server executable&lt;br /&gt;
* Linux Client dll ( .so )&lt;br /&gt;
* Client Server Model&lt;br /&gt;
* On Client Machine-&lt;br /&gt;
* Client executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* On Server&lt;br /&gt;
* Server executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* BR Listener installed&lt;br /&gt;
[ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
===) Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
e.g.	DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in:&lt;br /&gt;
C:\BR\SPOOL\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
  e.g.   SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
e.g.		C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11251</id>
		<title>4.30</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=4.30&amp;diff=11251"/>
		<updated>2020-05-13T15:39:29Z</updated>

		<summary type="html">&lt;p&gt;Mikhail.zheleznov: Properly included article, so that it shows up as part of the main 4.30 page, rather than having to open a new browser tab&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Status: [[Beta]]&lt;br /&gt;
&lt;br /&gt;
The prior versions were [[4.1]] and [[4.2]].&lt;br /&gt;
&lt;br /&gt;
As Of 08/30/2012&lt;br /&gt;
&lt;br /&gt;
==MISCELLANEOUS ENHANCEMENTS==&lt;br /&gt;
&lt;br /&gt;
“ON error-type IGNORE” now ignores the error instead of going to an Ignore label. This is effective for both ON statements and individual statement error exits. This could change the way your programs work if your Ignore statements do more than CONTINUE.  &lt;br /&gt;
&lt;br /&gt;
The general purpose ERROR exit implies SOFOW truncation. So statements that are governed by ERROR IGNORE also do SOFLOW truncation as needed. &lt;br /&gt;
&lt;br /&gt;
For client / server configurations:&lt;br /&gt;
SPOOLPATH   @: client-pathname&lt;br /&gt;
Sets the remote spool path on the client. In addition to regular spool files, this is where PDF files are created. SPOOLPATH can be set concurrently for both client and server by specifying two SPOOLPATH statements. The @: indicates remote.  &lt;br /&gt;
&lt;br /&gt;
The client-pathname has some unique characteristics:&lt;br /&gt;
Paths are assumed to be OS pathnames relative to the CLIENT_CURRENT_DIR folder, or the startup directory if CLIENT_CURRENT_DIR is not specified. &lt;br /&gt;
If a full pathname is specified it must begin with a colon.  ( e.g.  @::X:\path ) Otherwise it will be preceded with the path to the client current working directory. &lt;br /&gt;
Specifying a relative remote pathname is not compatible with CLIENT_CURRENT_DIR SYNC.&lt;br /&gt;
The status of SPOOLPATH and REMOTESPOOLPATH settings are displayed in response to the STATUS SUBSTITUTE command.  &lt;br /&gt;
&lt;br /&gt;
CHR$(6) is a field separator that displays as a space but causes the immediately preceding data to be right justified. This applies to both Native Windows Printing and PRINT FIELDS. &lt;br /&gt;
&lt;br /&gt;
MAT2STR, STR2MAT changes to trim outside of quotes, but not inside of quotes and to always quote MAT2STR when quotes are present.  &lt;br /&gt;
&lt;br /&gt;
STATUS USERS will display the WSID and name of each user logged in on the network. &lt;br /&gt;
The SQL statement SHOW USERS responds with the same information for ODBC users.&lt;br /&gt;
&lt;br /&gt;
BRERR$ is a new system function that display the description of BR ERR value.&lt;br /&gt;
BRERR$(error-code) returns the description of that code.&lt;br /&gt;
Examples-&lt;br /&gt;
When ERR returns 4270, BRERR$ will return “end of file”.&lt;br /&gt;
BRERR$(0875) returns “unrecognized data after field specification”&lt;br /&gt;
&lt;br /&gt;
For making it easier to configure ODBC with BRconfig.sys and to setup common configuration files for multiple platforms we have added:&lt;br /&gt;
@LINUX&lt;br /&gt;
@WINDOWS&lt;br /&gt;
@MAC&lt;br /&gt;
@ODBC&lt;br /&gt;
&lt;br /&gt;
For example, this could be important for DRIVE statements:&lt;br /&gt;
@LINUX DRIVE C:,/unix/path,.,\&lt;br /&gt;
@WINDOWS DRIVE C:,\\server\path,.,\&lt;br /&gt;
&lt;br /&gt;
Programs compiled with older versions of BR (3.3 – 3.8) can be listed accurately.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== GRID AND LIST CHANGES===&lt;br /&gt;
&lt;br /&gt;
Arrays  are automatically resized when receiving data from 2D INPUT operations. This also applies to grouped arrays. Automatic resizing only applies to one dimensional arrays and does not occur when INPUTing into two dimensional arrays.&lt;br /&gt;
&lt;br /&gt;
e.g.   &lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, ROW, ALL&amp;quot; : ( MAT Array1$,             MAT Array2$, MAT Array3, MAT Array4, MAT Array5$ )&lt;br /&gt;
&lt;br /&gt;
Where all arrays are one dimensional and may have the incorrect number of elements.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Three New Read Types====&lt;br /&gt;
&lt;br /&gt;
Auto Resizing applies. Selection Type must be ALL.&lt;br /&gt;
&lt;br /&gt;
The original 2D INPUT read types are:&lt;br /&gt;
  CNT	 - The number of cells specified.&lt;br /&gt;
  SUB	 - Read the Cell Subscript Values.&lt;br /&gt;
  CELL	 - Read each cell specified.&lt;br /&gt;
  ROWCNT - The number of rows specified.&lt;br /&gt;
  ROWSUB - The subscripts of the specified rows.&lt;br /&gt;
  ROW	 - Read all cells in each specified row.&lt;br /&gt;
&lt;br /&gt;
 HEADERS – The original PRINT FIELDS HEADER values.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, HEADERS,,NOWAIT&amp;quot; :&lt;br /&gt;
                                   (MAT HEADINGS$,MAT WIDTHS, MAT FORMS$)&lt;br /&gt;
&lt;br /&gt;
  COLCNT - The number of columns established by the header arrays.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, COLCNT, ALL&amp;quot; : numeric-variable&lt;br /&gt;
&lt;br /&gt;
These  are for generalized library routines to inspect passed controls. &lt;br /&gt;
&lt;br /&gt;
  SORT_ORDER - Provides a value of zero for each unsorted column and gives&lt;br /&gt;
the ascending sequence of column sorts that have occurred. If a column has&lt;br /&gt;
been reversed (double sorted) it&#039;s value will be negative.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row,col,LIST rows/cols, SORT_ORDER, ALL&amp;quot; : numeric-array&lt;br /&gt;
&lt;br /&gt;
Given the following history of sorting a four column GRID:&lt;br /&gt;
column 1 (descending most rescent)&lt;br /&gt;
column 2 (ascending first sorted)&lt;br /&gt;
column 3 (not sorted)&lt;br /&gt;
column 4 (sorted ascending)&lt;br /&gt;
&lt;br /&gt;
SORT_ORDER would return-&lt;br /&gt;
array(1) -&amp;gt;  -1&lt;br /&gt;
array(2) -&amp;gt;   3&lt;br /&gt;
array(3) -&amp;gt;   0&lt;br /&gt;
array(4) -&amp;gt;   2&lt;br /&gt;
&lt;br /&gt;
=== Restoring a User Sorted 2D Control===&lt;br /&gt;
&lt;br /&gt;
The syntax for sorting an array is currently:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column number }&lt;br /&gt;
&lt;br /&gt;
This has been extended to allow a numeric array of instead of a scalar. If an array is given, it is assumed to be in the same format that SORT_ORDER returns. The new format is:&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;nn,nn,GRID 10/40,SORT&amp;quot;: { column-number | numeric-array }&lt;br /&gt;
&lt;br /&gt;
Where the numeric-array has one element for each column left to right. BR will resort the columns in the requested order. &lt;br /&gt;
&lt;br /&gt;
The numeric array values indicating the order of column sorting to be performed do not need to exactly match the standard format. e.g Fractions are allowed, the values can fall within any range, and there does not need to be trailing zero elements for unsorted columns.&lt;br /&gt;
&lt;br /&gt;
=== A new Read Qualifier is available.===&lt;br /&gt;
{{:Displayed_Order}}&lt;br /&gt;
&lt;br /&gt;
===Masked 2D Display===&lt;br /&gt;
&lt;br /&gt;
LIST and GRID support the MASK operation-&lt;br /&gt;
&lt;br /&gt;
 PRINT FIELDS &amp;quot;row,col,LIST rows/cols,MASK&amp;quot; :  mask_array&lt;br /&gt;
&lt;br /&gt;
This restricts the rows (for both LIST and GRID) previously displayed to those corresponding to a “true” value in mask_array. A true value is represented in a umeric array as a value greater than zero. Negative values are not allowed in mask arrays. A string mask array may also be used with “T” and “F” values. The MASK stays in effect until 1) a new MASK is specified or 2) the contents of the control are changed with PRINT ( =, +, - see Output Operations in New Console.DOC). &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row,col,LIST rows/cols,MASK [,NOWAIT]&amp;quot; : mask_array&lt;br /&gt;
This reads the display mask setting for a 2D control.&lt;br /&gt;
&lt;br /&gt;
The mask array affects only the user presentation.. not the result set. Use RANGE processing or the CHG selection type to selectively read from a 2D control.&lt;br /&gt;
&lt;br /&gt;
== New Search Field Type: Filter ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter]]&lt;br /&gt;
== New Config: Filter_Delimiters  ==&lt;br /&gt;
&lt;br /&gt;
See [[Filter_Delimiters]]&lt;br /&gt;
&lt;br /&gt;
== FIELDS CHARACTER BY CHARACTER KEYBOARD CONTROL==&lt;br /&gt;
&lt;br /&gt;
[[^KeyStroke and ^DataChg]] introduced.&lt;br /&gt;
&lt;br /&gt;
== RANGE SELECTION TYPE==&lt;br /&gt;
&lt;br /&gt;
Valid current selection types are:&lt;br /&gt;
  SEL	- Read one or more selected items.&lt;br /&gt;
  SELONE - Select only one item.&lt;br /&gt;
  ALL	- Read all items in the control (except headings).&lt;br /&gt;
  CUR	- Current cell or row number.&lt;br /&gt;
  CHG	- All cells or rows who’s values have been changed by the operator.&lt;br /&gt;
&lt;br /&gt;
BR now supports the following additional selection types:&lt;br /&gt;
  RANGE - Specifies which portion of a 2D control is to be input.&lt;br /&gt;
  CELL_RANGE – A special type of output range.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== RANGE Input===&lt;br /&gt;
&lt;br /&gt;
In the following examples BR will redimension the receiving arrays as needed:&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row, col, LIST rows/cols, CELL, RANGE&amp;quot; : start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This reads the specified range of cells. BR redimensions MAT Data$ as needed.  Note that CELL may now be used with LIST. Previously, LISTs were only addressable by row. &lt;br /&gt;
&lt;br /&gt;
INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; :&lt;br /&gt;
             (start:=7), (end:=11), ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads the cells in rows 7 through 11. The receiving arrays are redimensioned as appropriate.&lt;br /&gt;
&lt;br /&gt;
  INPUT FIELDS &amp;quot;row, col, GRID rows/cols, ROW, RANGE&amp;quot; :&lt;br /&gt;
             MAT start, MAT end, ( MAT Data1$, MAT Data2$, MAT Data3 )&lt;br /&gt;
This reads one or more ranges of rows.&lt;br /&gt;
&lt;br /&gt;
A more detailed example of this is:&lt;br /&gt;
  100 -- create and populate a LIST control --&lt;br /&gt;
  ........&lt;br /&gt;
  200 MAT START(3) : MAT END(3)&lt;br /&gt;
  210 READ MAT START, MAT END&lt;br /&gt;
  220 DATA 7,21,33&lt;br /&gt;
  230 DATA 11,21,38&lt;br /&gt;
  240 INPUT FIELDS &amp;quot;row, col, LIST rows/cols, ROW, RANGE&amp;quot; : MAT START,&lt;br /&gt;
            MAT END, ( MAT Array1$, MAT Array2, MAT Array3$ )&lt;br /&gt;
&lt;br /&gt;
This reads 12 rows of data ( row 7-11, row 21 and rows 33-38 ).&lt;br /&gt;
&lt;br /&gt;
=== RANGE Output===&lt;br /&gt;
&lt;br /&gt;
By default, RANGE output refers to rows. The special keyword CELL_RANGE is used to denote the specification of cell ranges. Additionally, the use of scalars versus arrays for start and end values determines important characteristics of the output process. &lt;br /&gt;
&lt;br /&gt;
4c) Using Scalars For Range Specification&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7, 8, GRID 10/75, RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
This replaces the values in rows numbered &#039;start&#039; through &#039;end&#039; with the data in MAT Data$. The size of MAT Data$ must be a multiple of the number of columns in the GRID or an error is generated.&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7, 8, LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$,&lt;br /&gt;
                                          MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
This replaces the values in ROWs numbered &#039;start&#039; through &#039;end&#039; with the data from MATs NAME$, CITY$, AGE and WEIGHT. The data arrays must all be dimensioned the same.&lt;br /&gt;
&lt;br /&gt;
=== Row Insertion and Deletion===&lt;br /&gt;
&lt;br /&gt;
The number of rows being output do not need to match the number of rows being replaced. To delete a range of rows, output one or more grouped arrays with zero elements.&lt;br /&gt;
&lt;br /&gt;
Examples- Using the following statement various scenarios are described.&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,LIST 10/75, RANGE&amp;quot;: start, end, (MAT NAME$,&lt;br /&gt;
                                          MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
&lt;br /&gt;
  Start=7, end=11, and the arrays have been DIMed to nine elements&lt;br /&gt;
  Result- Nine rows replace five, and the total content of the control is&lt;br /&gt;
          expanded by 4 rows.&lt;br /&gt;
&lt;br /&gt;
  Start=7, end=11, and the arrays are DIMed to zero elements&lt;br /&gt;
  Result- Five rows are deleted, and the total size of the control is&lt;br /&gt;
          reduced by 5 rows.&lt;br /&gt;
&lt;br /&gt;
  Start=7, end=0 (anything less than 7), and the arrays are DIMed to&lt;br /&gt;
           support three rows&lt;br /&gt;
  Result- Three rows are inserted ahead of row seven and the total content&lt;br /&gt;
          of the control is expanded by three rows&lt;br /&gt;
&lt;br /&gt;
  Start=5000, end={any value}, the control only has 482 rows, and the source&lt;br /&gt;
          arrays are DIMed to support eleven rows&lt;br /&gt;
  Result- Eleven rows are appended to the end of the control and become&lt;br /&gt;
          rows 483 through 493.&lt;br /&gt;
&lt;br /&gt;
=== Outputting Ranges of Cells===&lt;br /&gt;
&lt;br /&gt;
Ranges of cells may be output in conjunction with the CELL_RANGE keyword.&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,LIST 10/75, CELL_RANGE&amp;quot;: start, end, (MAT NAME$,&lt;br /&gt;
                                          MAT CITY$, MAT AGE, MAT WEIGHT)&lt;br /&gt;
                                - or -&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, end, MAT Data$&lt;br /&gt;
&lt;br /&gt;
In this case, start and end specify cells instead of rows. If insertion or deletion is indicated by dimensioning the data arrays to greater or fewer elements than are being replaced, then the data must be a multiple of the number of columns. Insertion and deletion is only valid in terms&lt;br /&gt;
of rows, even when cell subscripts are used to specify ranges. In such cases, if the cell subscripts are not on row boundaries, an error is generated.&lt;br /&gt;
&lt;br /&gt;
PRINT FIELDS &amp;quot;7,8,GRID 10/75, CELL_RANGE&amp;quot;: start, start, Data$&lt;br /&gt;
In this example, the value in one cell is replaced with the content of a scalar.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Using Arrays For RANGE Specification===&lt;br /&gt;
&lt;br /&gt;
If the start and end specifications are arrays, denoting multiple ranges, there must be a one to one correspondence between the number of rows specified and those in the data. This method implies replacement only and insertion or deletion is not allowed.&lt;br /&gt;
&lt;br /&gt;
The data flow that this feature was designed to support is one where the user is presented with a LIST or GRID where multiple rows have been either selected or changed before returning control to the program and the program is responding by updating something on those rows.&lt;br /&gt;
&lt;br /&gt;
The program begins by presenting a 2D control to the user and reading the the control with type ROWSUB or SUB. Type SUB only works for GRIDs where all colmns have the same data type. Of course the subscripts are read into a numeric array which BR redimensions as appropriate.  Then the program reads the changed or selected data with NOWAIT. (This resets the CHG flags in the control.) The program then changes either row (ROWSUB) or cell (SUB)&lt;br /&gt;
data and outputs the results using the subscript array as both the start and end specification. Other scenarios are possible but this is the primary intended use.&lt;br /&gt;
&lt;br /&gt;
An example of this is:&lt;br /&gt;
  100 -- create and populate a GRID --&lt;br /&gt;
  ........&lt;br /&gt;
  200 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROWSUB,CHG&amp;quot;: MAT Rowsubs&lt;br /&gt;
         (Reading subscripts does not reset the CHG flags in the control.)&lt;br /&gt;
  210 INPUT FIELDS &amp;quot;row,col,GRID rows/cols,ROW,CHG,NOWAIT&amp;quot;: ( MAT Data1$,&lt;br /&gt;
                                  MAT Data2, MAT Data3$ )&lt;br /&gt;
          BR redimensions the receiving arrays as needed.&lt;br /&gt;
         (Reading the data also resets the CHG flags in the control.)&lt;br /&gt;
&lt;br /&gt;
  220 -- process the changed rows now present in the data arrays --&lt;br /&gt;
  ........&lt;br /&gt;
  300 PRINT FIELDS &amp;quot;row,col,GRID rows/cols,RANGE&amp;quot;: MAT Rowsubs,&lt;br /&gt;
                   MAT Rowsubs, ( MAT Data1$, MAT Data2, MAT Data3$ )&lt;br /&gt;
&lt;br /&gt;
This outputs the updated rows.&lt;br /&gt;
&lt;br /&gt;
== FINE GRAIN FIELD POSITIONING==&lt;br /&gt;
ROW/COL and ROWS/COLS in FIELDS operations may be expressed as decimal fractions.&lt;br /&gt;
&lt;br /&gt;
== LOGGING ENHANCEMENTS==&lt;br /&gt;
The debug versions of BR now expect you to use a LOGGING configuration statement. This enables BR to post exit messages during unexpected terminations.&lt;br /&gt;
&lt;br /&gt;
A system function called DEBUG_STR( message-level, string-value ) will, depending on LOG LEVEL, send data to the LOGGING file as well as to the MyEditBR debugger if it is attached, or optionally to the command console if the debugger is not attached and GUI is ON. This lets you freely put trace related informational statements into your code without affecting normal processing.  &lt;br /&gt;
&lt;br /&gt;
The LOGGING configuration statement now has two additional optional parameters:&lt;br /&gt;
&lt;br /&gt;
   LOGGING  loglevel,  logfile   [ ,DEBUG_LOG_LEVEL=nn ]   [ ,+CONSOLE ]&lt;br /&gt;
&lt;br /&gt;
Note- Logfile is a native OS filename.  Second and subsequent occurrences of the LOGGING statement may omit loglevel and the log filename.&lt;br /&gt;
	&lt;br /&gt;
DEBUG_LOG_LEVEL specifies the log level for debugging log messages Independently of the standard log level. If not specified the Debug_Log_Level is set to the standard log level.&lt;br /&gt;
&lt;br /&gt;
+CONSOLE applies only when GUI is ON and specifies that all logging messages also go to the console and the console is to be left visible when not attached to MyEditBR. ( Console logging output is suppressed when GUI is OFF. )&lt;br /&gt;
&lt;br /&gt;
Message Levels are compared with Log Levels during the filtering process. The Logging Level is meant to specify the level of detail to be logged, with greater detail logged at higher log levels.  &lt;br /&gt;
&lt;br /&gt;
The following types of messages are written to the LOGGING file:&lt;br /&gt;
&lt;br /&gt;
Config error messages based on their assigned level of importance.&lt;br /&gt;
&lt;br /&gt;
DEBUG_STR() messages where message-level is equal to or less than the DEBUG_LOG_LEVEL.&lt;br /&gt;
&lt;br /&gt;
Log levels 0, 1, 2 and 3-&lt;br /&gt;
  System generated warning messages such as OS failures and abnormal exits.&lt;br /&gt;
Log level 5 or above-&lt;br /&gt;
  User Logon data, including any logon attempts.&lt;br /&gt;
Log level 6 or above-&lt;br /&gt;
  Starting a BR program, exiting.&lt;br /&gt;
Log level 8 or above-&lt;br /&gt;
   Commands such as COPY plus shell calls with parameters. &lt;br /&gt;
   PDF printing events.&lt;br /&gt;
Log level 11 or above-&lt;br /&gt;
   Any PRINT output that goes to the console is also logged (GUI ON only).&lt;br /&gt;
Log level 12 or above-&lt;br /&gt;
  TRACE, and DISPLAY messages.&lt;br /&gt;
Log level 13 or above-&lt;br /&gt;
  Lots of what the system is doing now messages.&lt;br /&gt;
&lt;br /&gt;
Any DEBUG_STR() calls with a level &amp;gt;10 are deemed to be message level 10.&lt;br /&gt;
&lt;br /&gt;
Logging was added to PDF creation. Logging of minor events that happen during the printing process are logged at log level 8.  Errors are logged at a lower level. Logging was also improved with respect to loading older versions of pdflib.&lt;br /&gt;
Note- As a diagnostic, the following command is quite useful: &lt;br /&gt;
DIR &amp;gt;PDF:/READER&lt;br /&gt;
&lt;br /&gt;
ODBC Logging was substantially increased.&lt;br /&gt;
&lt;br /&gt;
Log Level Indication is given in Log Messages:&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
Setting logging to log file logfile.txt log level 10.&lt;br /&gt;
  (6) - 08/25/2011 11:33:53&lt;br /&gt;
The BRConfig.sys file is C:\Users\dan\programs\cygwin\home\dan\br-wx\br\winbuild\dllbuild\output\brconfig.sys&lt;br /&gt;
The (6) here is the log level.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== CSV AND XML PARSING ENHANCEMENTS==&lt;br /&gt;
The [[string to mat]] and [[mat to string]] functions have been extended to ease parsing of CSV and XML data. &lt;br /&gt;
&lt;br /&gt;
STR2MAT( str$, MAT zzz$ [, [MAT] Sep$ [, flags$]] )&lt;br /&gt;
Where Sep$ may be an array and flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Q and QUOTES denote standard BR quote processing. The trim flags denote post processing of extracted elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
When Sep$ is an array, then any or all of the specified values are deemed to represent a single separator with the qualification that any one separator, cannot occur more than once in a string of adjacent separators. To restate this, when elements of a Sep$ array occur adjacent to each other within the source string, they are grouped as a separator substring.&lt;br /&gt;
Sep$ elements cannot occur more than once in a separator substring. When they do, it denotes the specification of a null element.  e.g. two successive commas or two successive occurrences of CR+LF both denote null elements. Essentially when Sep$ elements are &#039;consumed&#039; by their recognition within the source string, then they cannot be re-recognized without inserting a null element into the output array. &lt;br /&gt;
=== Quote Processing ===&lt;br /&gt;
Quotation marks suppress the recognition of separators in accordance with the following rules.&lt;br /&gt;
Standard BR Quote Processing&lt;br /&gt;
When examining str$ left to right, the first character (and the first character after each separator) is checked to see if is either (&#039;) or (&amp;quot;). If it is either of those then it activates quotation processing which suppresses the recognition of separators until quotation processing is deactivated. The first character thus becomes the governing quote type until quotation processing is deactivated.&lt;br /&gt;
&lt;br /&gt;
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 an embedded occurrence of the quote character.&lt;br /&gt;
Examples&lt;br /&gt;
&amp;quot;abc,def&amp;quot; -&amp;gt; abc,def    where the comma is not recognized as a separator and is part of the data&lt;br /&gt;
abc&amp;quot;def -&amp;gt; abc&amp;quot;def    naturally embedded quotes may occur anywhere within a string after the first character&lt;br /&gt;
&amp;quot;abc&amp;quot;def&amp;quot; -&amp;gt; abcdef&amp;quot;   quotation processing is deactivated by the center quote mark&lt;br /&gt;
&amp;quot;abcdef&amp;quot; -&amp;gt; abcdef   normal data&lt;br /&gt;
&amp;quot;abc&#039;def&amp;quot; -&amp;gt; abc&#039;def   the single quote is treated like any other character while double quotes govern&lt;br /&gt;
&#039;abc&amp;quot;def&#039; -&amp;gt; abc&amp;quot;def   double quotes are treated like any other character while single quotes govern&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def   pairs of governing quotes denote a single embedded quote&lt;br /&gt;
&amp;quot;abc&amp;quot;&amp;quot;&amp;quot;def&amp;quot; -&amp;gt; abc&amp;quot;def&amp;quot;   the third successive occurrence deactivates quote processing which began with the first quote&lt;br /&gt;
&lt;br /&gt;
MAT2STR( MAT zzz$, str$ [, sep$ [, flags$]] )&lt;br /&gt;
Where flag$ is in the format:&lt;br /&gt;
[ quote-type ] [ :LTRM ] | [ :TRIM ] | [ :RTRM ]&lt;br /&gt;
Where quote-type can be Q, QUOTES, (&#039;), or (&amp;quot;), case insensitive. Quote-type denotes that each element should be enclosed in quotation marks. The trim flags denote pre-processing of array elements and the leading colon is only present when quote-type is specified.&lt;br /&gt;
If Q or QUOTES is specified then BR automatically determines which quote type to apply as follows:&lt;br /&gt;
First the element is unpacked. That is, if it is contained in quotes, the quotes are stripped and embedded pairs are singled. 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.&lt;br /&gt;
Examples&lt;br /&gt;
Quote Type is Q or QUOTES&lt;br /&gt;
abcdef -&amp;gt; &amp;quot;abcdef&amp;quot;&lt;br /&gt;
abc&#039;def -&amp;gt; &amp;quot;abc&#039;def&amp;quot;&lt;br /&gt;
abc&amp;quot;def -&amp;gt; &#039;abc&amp;quot;def&#039;&lt;br /&gt;
abc&amp;quot;&amp;quot;def -&amp;gt; ‘abc&amp;quot;&amp;quot;def’     embedded quotes are left intact when quotes are not active&lt;br /&gt;
&#039;abcdef -&amp;gt; &amp;quot;&#039;abcdef&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quote Type is &#039; ( quote type single )&lt;br /&gt;
abcdef -&amp;gt; &#039;abcdef&#039;&lt;br /&gt;
&#039;abcdef -&amp;gt; &#039;&#039;&#039;abcdef&#039;   single quotes get doubled when embedded in single quotes&lt;br /&gt;
&amp;quot;abcdef -&amp;gt; &#039;&amp;quot;abcdef&#039;   leading double quote is treated normally&lt;br /&gt;
&lt;br /&gt;
Quote type double mirrors quote type single.&lt;br /&gt;
MAT2STR and STR2MAT trim outside of quotes but not inside of quotes. Also MAT2STR always adds quotes when quotes are present in the data.  &lt;br /&gt;
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 three to seven dimensions.&lt;br /&gt;
Example&lt;br /&gt;
Given the following two dimensional array zzz$ containing the values-&lt;br /&gt;
    1            2&lt;br /&gt;
    3            4&lt;br /&gt;
&lt;br /&gt;
The following statements-&lt;br /&gt;
    10 Sep$(1)=&amp;quot;,&amp;quot;&lt;br /&gt;
    20 Sep$(2)=hex$(&amp;quot;0D0A&amp;quot;) ! CRLF&lt;br /&gt;
    30 MAT2STR( MAT zzz$,  str$, MAT Sep$ )&lt;br /&gt;
    40 PRINT str$&lt;br /&gt;
&lt;br /&gt;
Will produce-&lt;br /&gt;
    1,2&lt;br /&gt;
    3,4&lt;br /&gt;
&lt;br /&gt;
=== CSV Parsing Example===&lt;br /&gt;
Parsing CSV data files is now quite easy, the following code snippet demonstrates how to open a CSV/Tab File, read in the fields from the header, and then loop through  the records.&lt;br /&gt;
 01000    dim CSV_LINE$*999,CSV_FILE$*256, CSV_DELIM$*1, CSV_HEADER$*999, &lt;br /&gt;
CSV_FIELDS$(1)*40, CSV_DATA$(1)*60&lt;br /&gt;
 01020    form C,&amp;quot; &amp;quot;&lt;br /&gt;
 01040    let CSV_FILE$=&amp;quot;Sample_File.tab&amp;quot; : let TAB$=CHR$(9)&lt;br /&gt;
 01060    open #(CSV_HANDLE:=10): &amp;quot;name=&amp;quot;&amp;amp;CSV_FILE$&amp;amp;&amp;quot;, shr&amp;quot;, display,input &lt;br /&gt;
 01080    linput #CSV_HANDLE: CSV_HEADER$&lt;br /&gt;
 01100    let CSV_DELIM$=TAB$&lt;br /&gt;
 01120    if POS(CSV_HEADER$,TAB$) &amp;lt;= 0 then &lt;br /&gt;
 01140       let CSV_DELIM$=&amp;quot;,&amp;quot;&lt;br /&gt;
 01160    end if &lt;br /&gt;
 01180    let STR2MAT(CSV_HEADER$, MAT CSV_FIELDS$, CSV_DELIM$, &amp;quot;QUOTES:TRIM&amp;quot;)&lt;br /&gt;
 01200    print using 1020: MAT CSV_FIELDS$&lt;br /&gt;
 01220    do &lt;br /&gt;
 01240       linput #CSV_HANDLE: CSV_LINE$ eof Exit_Csv&lt;br /&gt;
 01260       let STR2MAT(CSV_LINE$,MAT CSV_DATA$,CSV_DELIM$,&amp;quot;Q:trim&amp;quot;)&lt;br /&gt;
 01280       print using 1020: MAT CSV_DATA$&lt;br /&gt;
 01300    loop &lt;br /&gt;
 01320 Exit_Csv: !&lt;br /&gt;
&lt;br /&gt;
You might wish to copy any CSV file to Sample_File.tab and run this program to view the content.&lt;br /&gt;
&lt;br /&gt;
=== XML Parsing Examples===&lt;br /&gt;
&lt;br /&gt;
STR2MAT may also be used to Parse XML data.&lt;br /&gt;
This is a bit more complex than parsing CSV files, but remains a powerful tool.&lt;br /&gt;
The following example will parse XML$ into &amp;quot;MAT XML_LINE$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  10 DIM XML$*999999,XML_LINE$(1)*32000&lt;br /&gt;
  20 XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
  100 LET Str2mat(XML$,Mat XML_LINE$,&amp;quot;&amp;gt;&amp;quot;,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
This makes the parsing of XML a bit more convenient. The following XML sample shows how the function will parse the data&lt;br /&gt;
&lt;br /&gt;
Input:&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Output:&lt;br /&gt;
  &amp;lt;XML&lt;br /&gt;
  &amp;lt;NODE&lt;br /&gt;
  &amp;lt;ITEM&lt;br /&gt;
  ITEM VALUE&amp;lt;/ITEM&lt;br /&gt;
  &amp;lt;/NODE&lt;br /&gt;
  &amp;lt;/XML&lt;br /&gt;
&lt;br /&gt;
While the above technique is useful, a more complete and useful technique can be performed if the Node names are known. You may use an array of SEP$ values to parse the data.  Take the following example:&lt;br /&gt;
&lt;br /&gt;
 100    dim XML$*999999,XML_LINE$(1)*32000,SEP$(4)*32&lt;br /&gt;
 110    let XML$=&amp;quot;&amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&amp;lt;/ITEM&amp;gt;&amp;lt;ITEM2&amp;gt;ITEM2 VALUE&amp;lt;/ITEM2&amp;gt;&amp;lt;/NODE&amp;gt;&amp;lt;/XML&amp;gt;&amp;quot;&lt;br /&gt;
 120    read MAT SEP$&lt;br /&gt;
 130    data &amp;lt;/XML&amp;gt;,&amp;lt;/NODE&amp;gt;,&amp;lt;/ITEM&amp;gt;,&amp;lt;/ITEM2&amp;gt;&lt;br /&gt;
 140    let STR2MAT(XML$,MAT XML_LINE$,MAT SEP$,&amp;quot;TRIM&amp;quot;)&lt;br /&gt;
 150    print MAT XML_LINE$&lt;br /&gt;
&lt;br /&gt;
This program would return the following results:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;XML&amp;gt;&amp;lt;NODE&amp;gt;&amp;lt;ITEM&amp;gt;ITEM VALUE&lt;br /&gt;
  &amp;lt;ITEM2&amp;gt;ITEM2 VALUE&lt;br /&gt;
&lt;br /&gt;
Notice that &amp;quot;Nested Nodes&amp;quot; are listed before the initial data, this may be used to identify the node.&lt;br /&gt;
&lt;br /&gt;
== NEW DLL STRUCTURE OF BUSINESS RULES!==&lt;br /&gt;
&lt;br /&gt;
As of Release 4.3 Business Rules! has been restructured into the following modules:&lt;br /&gt;
[[brserver.exe]] – The BR Server module accessed by Client-Server configurations. Brserver.exe also operates as what is now viewed as the Standard Model. If it is invoked by brlistener, then it act as brserver. If it is simply executed, it acts as brcombined. However, when operating as the standard model, it needs to have brclient.dll in the same directory as brserver.&lt;br /&gt;
[[brclient.exe]] – The program that the user accesses in Client-Server configurations&lt;br /&gt;
[[brclient.dll]] – The client processing program that correlates with the brserver edition.&lt;br /&gt;
[[npbrclient.dll]] - The standard (non-IE) browser plugin dll&lt;br /&gt;
[[iebrclient.dll]] – Internet Explorer plugin dll&lt;br /&gt;
&lt;br /&gt;
Client installation is done by placing brclient.exe and brclient.dll on the client system and referencing brclient.exe in an icon. Server installation is done by placing brserver.exe and brclient.dll on the server and referencing brserver.exe in the brlistener.conf file. Exe files may be renamed as desired. The name of the released brclient.dll modules will be lengthy and must not be changed because BR relies on the DLL names for version identification. &lt;br /&gt;
&lt;br /&gt;
You will need one of the following possible configurations:&lt;br /&gt;
* Workstation Standard Model&lt;br /&gt;
* Server executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* Linux Terminal Support&lt;br /&gt;
* Server executable&lt;br /&gt;
* Linux Client dll ( .so )&lt;br /&gt;
* Client Server Model&lt;br /&gt;
* On Client Machine-&lt;br /&gt;
* Client executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* On Server&lt;br /&gt;
* Server executable&lt;br /&gt;
* Workstation Client dll&lt;br /&gt;
* BR Listener installed&lt;br /&gt;
[ Linux Client dll for Linux terminal access ]&lt;br /&gt;
&lt;br /&gt;
The 32 and 64 bit versions of servers and clients can be intermixed. However dlls must be the in same bit class as the modules that call them.  Put your BR bmp files ( drawsunk.bmp, startup.bmp etc. ) in the BR server executable directory. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Updates will pertain to Processor DLLs while the user interfaces will remain as installed. Client DLLs will be automatically uploaded when corresponding server DLLs are accessed in the event they are not already present on the client.&lt;br /&gt;
&lt;br /&gt;
The client can be accessed from within a browser by initiating it with HTML which can specify an embedded window or a separate independent window. In all cases opening a window with PARENT=NONE creates a separate window. &lt;br /&gt;
&lt;br /&gt;
=== BR Adjunctive Files===&lt;br /&gt;
&lt;br /&gt;
The BR executable is now considered to be where the BR server actually resides, irrespective of Drive statements and current working directories. &lt;br /&gt;
&lt;br /&gt;
The following files are located in the BR executable directory by default:&lt;br /&gt;
BR server executable&lt;br /&gt;
BRconfig.sys&lt;br /&gt;
BRserial.dat&lt;br /&gt;
BRserver.dat&lt;br /&gt;
WBcmd.wbh - BR help files&lt;br /&gt;
Server Dlls&lt;br /&gt;
Client Dlls for uploading as needed&lt;br /&gt;
System Image files – linedraw, etc. - typically BMPs&lt;br /&gt;
===) Exceptions===&lt;br /&gt;
&lt;br /&gt;
If [[WBcmd.wbh]] doesn&#039;t exist in the BR executable directory then BR looks for it in the initial directory specified by the first drive statement. ( deprecated – will be eliminated at some point)  ONQPATH currently defaults to this initial path as well. ( this will remain )&lt;br /&gt;
&lt;br /&gt;
If the BRconfig file is not present in the BR executable directory then BR looks for it in the current working directory at the time of BR invokation. &lt;br /&gt;
&lt;br /&gt;
The SPOOLPATH :OS-fullpath  configuration statement specifies where print spool files are temporarily stored during printing.  SPOOLPATH defaults to a spool directory that runs off of the BR root of the first drive statement. If no such spool directory exists and SPOOLPATH is not specified then BR creates one.&lt;br /&gt;
e.g.	DRIVE   J:, C:\BR, x, \MYAPP   would result in spool files being placed in:&lt;br /&gt;
C:\BR\SPOOL\&lt;br /&gt;
&lt;br /&gt;
SPOOLPATH @::client-OS-fullpath   specifies where on the client spool files are to be placed.  &lt;br /&gt;
  e.g.   SPOOLPATH  @::C:\BR\SPOOL  -or whatever other full path is desired-&lt;br /&gt;
&lt;br /&gt;
The @:  tells BR that this path is on the client. The second colon says the path is independent of drive specifications. &lt;br /&gt;
&lt;br /&gt;
WORKPATH defaults to the BR root of the first drive statement:&lt;br /&gt;
e.g.		C:\BR\&lt;br /&gt;
&lt;br /&gt;
BRconfig.sys INCLUDE statements are relative to the location of the file containing the INCLUDE statement ( the parent ).  CONFIG command INCLUDE statements are relative to the current directory at the time the command is issued.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Licensing Restrictions===&lt;br /&gt;
&lt;br /&gt;
As of [[4.20H]], [[brserial]] files must be specific to the first decimal position of the [[release]] of BR that is being used. ( e.g. 4.2x versus 4.3x )&lt;br /&gt;
&lt;br /&gt;
To accommodate more than one brserial level, BR first looks for its own suffix ( 42 or 43 ) before looking for a dat file. From now on it is most useful to name your brserial files either BRSERIAL.42 or BRSERIAL.43, etc.&lt;br /&gt;
&lt;br /&gt;
== CLIENT SERVER RECONNECT Configuration Statement==&lt;br /&gt;
&lt;br /&gt;
CLIENT_SERVER     RECONNECT_AFTER=20   RECONNECT_TIME=120&lt;br /&gt;
&lt;br /&gt;
BR sends idle packets between the client and the server every 2 seconds. This statement specifies that after 20 seconds of not receiving such packets BR will attempt to reconnect.  This reconnect process can last up to a maximum of 120 seconds, after which BR will issue a “lost connection” error and begin processing in unattended mode. &lt;br /&gt;
&lt;br /&gt;
You can change the above period lengths with the above CONFIG statement.&lt;br /&gt;
&lt;br /&gt;
When BR runs unattended, it normally terminates processing if the program attempts to wait for keyboard input. However, after a lost connection error, if a library program attempts to wait for keyboard input the library function is terminated, the calling statement receives control, and the lost connection error is issued again. This supports error trapping in the calling program so an orderly shutdown can be performed. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== AUTOIT SUPPORT==&lt;br /&gt;
&lt;br /&gt;
[[AutoIt]] is a free keyboard simulation program with very powerful automating capabilities. It can be used to access windows, read data from spreadsheets, write to display files and enter data in screens. There is a separate Window Information utility that comes with Autoit which displays what Autoit sees when windows are active. This has produced ambiguous information in the past. &lt;br /&gt;
&lt;br /&gt;
R99C999 (BR row &amp;amp; col) now appears in the text field of BR labels.&lt;br /&gt;
&lt;br /&gt;
Individual BR input fields may be referenced in Autoit as    EditNN    where NN is the INPUT FIELDS subscript (CURFLD) of the field.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== ENVIRONMENT INTERROGATION==&lt;br /&gt;
&lt;br /&gt;
ENV$(&amp;quot;STATUS [ .sub-keyword ] ... &amp;quot; [, mat config$ [, search-arg] ...] )&lt;br /&gt;
&lt;br /&gt;
ENV$ returns a string or, in the event MAT CONFIG$ is provided, ENV$ redimensions and loads it. For a list of valid keywords issue a STATUS ENV command. If an array is specified, it may be followed by one or more case insensitive substrings which are regarded as restricting search arguments.&lt;br /&gt;
&lt;br /&gt;
e.g.  ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;)      returns “WINDOWS”&lt;br /&gt;
&lt;br /&gt;
The following program displays all STATUS information that contains the word “file”:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
The above program produces the following output:&lt;br /&gt;
&lt;br /&gt;
 CHAINDFLT - Look for object files with source first.&lt;br /&gt;
 EDITOR C:\PROGRAM FILES\MILLS ENTERPRISE\MYEDITBR\MYEDITBR.EXE&lt;br /&gt;
 FILENAMES LOWER_CASE&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files&lt;br /&gt;
 SPOOLCMD prt.bat [SPOOLFILE] [COPIES] [PRINTER]&lt;br /&gt;
 Server File: :c:\wbserver.dat&lt;br /&gt;
 BR Config File: :C:\ADS\SYS\br.d\brconfig.sys&lt;br /&gt;
 Executable File: :C:\ADS\SYS\br.d\ &lt;br /&gt;
 brserver-430beta+q-Win32-DebugEfence-2011-03-20.exe&lt;br /&gt;
 Serial File: :C:\ADS\SYS\br.d\brserial.dat&lt;br /&gt;
 Workfile path: :c:\ads&lt;br /&gt;
 Open File #  0  :CON:&lt;br /&gt;
&lt;br /&gt;
If I just want the options with the word file then I would use:&lt;br /&gt;
&lt;br /&gt;
 00100    dim CONFIG$(1)*100&lt;br /&gt;
 00120    let ENV$(&amp;quot;STATUS.CONFIG.OPTION&amp;quot;,MAT CONFIG$,&amp;quot;file&amp;quot;)&lt;br /&gt;
 00140    print MAT CONFIG$&lt;br /&gt;
&lt;br /&gt;
Which produces:&lt;br /&gt;
 OPTION 23 is OFF - prevent data conversion errors from moving file position&lt;br /&gt;
 OPTION 25 is ON - make FILE$(0) be CON: if in windows&lt;br /&gt;
 OPTION 26 is OFF - suppress creation of .BAK files&lt;br /&gt;
 OPTION 29 is ON - save programs as .WB files&lt;br /&gt;
 OPTION 33 is 64 - locking position for large file support&lt;br /&gt;
 OPTION 49 is OFF - use relative path for spool file&lt;br /&gt;
 OPTION 51 is OFF - recover deleted records for all files &lt;br /&gt;
&lt;br /&gt;
Note that while keywords are case insensitive, they must be correctly specified, whereas search arguments are more “friendly”. For a complete list of valid keywords, issue the command:&lt;br /&gt;
&lt;br /&gt;
	STATUS ENV -p&lt;br /&gt;
&lt;br /&gt;
Some of the new keywords supported are:&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM&amp;quot;) is &amp;quot;WINDOWS&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-12&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;32&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;Windows 7&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;CLIENT_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;6.1&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM&amp;quot;) is &amp;quot;LINUX&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_TYPE&amp;quot;) is &amp;quot;DebugEfence&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BUILD_DATE&amp;quot;) is &amp;quot;2011-05-13&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.BR_BITS&amp;quot;) is &amp;quot;64&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_BITS&amp;quot;) is &amp;quot;&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NAME&amp;quot;) is &amp;quot;#36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010&amp;quot;&lt;br /&gt;
*ENV$(&amp;quot;SERVER_PLATFORM.OS_VERSION_NUMBER&amp;quot;) is &amp;quot;2.6.32-22-server&amp;quot;	&lt;br /&gt;
*BR_MODEL		  “CLIENT/SERVER” or “COMBINED”&lt;br /&gt;
&lt;br /&gt;
== NEW WORLD SQL SUPPORT==&lt;br /&gt;
&lt;br /&gt;
CONFIG DATABASE db-ref  DSN=dsn-ref  [, USER= department | LOGIN_NAME | ? ]&lt;br /&gt;
     [, {PASSWORD= dept-password | BR_PASSWORD | ?} | PASSWORDD=encrypted-passwd ]&lt;br /&gt;
? indicates prompt&lt;br /&gt;
BR_PASSWORD indicates the password used during client login. If running the standard model ( not client-server ) then this is equivalent to “?”.&lt;br /&gt;
encrypted-passwd is the DB password encrypted with the key stated in OPTION 66.&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE db-ref  CONNECTSTRING=&amp;quot;Driver={Microsoft Access Driver (*.mdb)}&lt;br /&gt;
e.g.       DBQ=C:\inetpub\wwwroot\BegASP\Chapter.14\Contact.mdb&amp;quot;&lt;br /&gt;
            - or -&lt;br /&gt;
CONFIG DATABASE ODBC-MANAGER&lt;br /&gt;
This will invoke the ODBC Manager to define or identify a file DSN.&lt;br /&gt;
&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref&amp;quot; , SQL &amp;quot;sql-statement&amp;quot;, OUTIN&lt;br /&gt;
             - or -&lt;br /&gt;
OPEN #20: &amp;quot;DATABASE= db-ref, Name= filename&amp;quot; , SQL, OUTIN&lt;br /&gt;
     - filename refers to a DISPLAY file containing an SQL statement&lt;br /&gt;
       that gets executed when a WRITE statement is processed -&lt;br /&gt;
&lt;br /&gt;
===Sequence of Operations===&lt;br /&gt;
&lt;br /&gt;
1. Begin processing with a WRITE statement.&lt;br /&gt;
2. If the WRITE contains an IO list of values then it is used to populate the &#039;filename&#039; SQL before it is executed. In this process IO list values replace question marks in the original SQL, positionally left to right.  These question marks only work with SQL arguments that refer to stored data. Question marks cannot be specified where SQL keywords or table column names appear. &lt;br /&gt;
3. This may or may not produce a result set. If it does, the result set may be processed like a BR file opened RELATIVE. Some operations that use file positioning may be slow since the whole result set may not be in memory immediately. Simple sequential access should be fairly quick.&lt;br /&gt;
4. Once SQL has been populated by an IOlist, it may be reused with the same values by issuing a WRITE with no IOlist.&lt;br /&gt;
5. READ IOlist variable associations are positional with each READ accessing one row of values.&lt;br /&gt;
&lt;br /&gt;
=== SQL Date Format Functions===&lt;br /&gt;
&lt;br /&gt;
A$ = SQL_DATE$(BR-date-string,&amp;quot;format-mask&amp;quot;)    ! format date for storage&lt;br /&gt;
B$ = BR_DATE$( SQL-date-string,&amp;quot;format-mask&amp;quot;)   ! unpack DB date value&lt;br /&gt;
&lt;br /&gt;
* Note: SQL DATETIME fields are &amp;quot;Packed for Storage&amp;quot;, but &amp;quot;DATE&amp;quot; fields are returned as a CCYY-MM-DD string in a SQL Query.  DATE returns &amp;quot;BLANK&amp;quot; for &amp;quot;Empty or Null Date&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== SQL Table Interrogation===&lt;br /&gt;
&lt;br /&gt;
“ENV$ (STATUS)” has been extended to interrogate database connections and ODBC data sources. A program called ENVDB.BRS has been written to demonstrate how this extension works and to show how to setup linkage to a database or ODBC data source. Run the program as is to bring up the Microsoft ODBC manager. Then select a data source and look at the output from the program. This will also show you how to get and use connect strings. In this example lines 1900 and 2000 accomplish the same open as line 1800 in my environment. &lt;br /&gt;
&lt;br /&gt;
Try it on your Windows workstation. As long as you have one or more ODBC drivers supported you can use it without having to install a database. You can even use it to interrogate Excel files because Microsoft provides an ODBC driver for that. &lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate database interrogation entry is:&lt;br /&gt;
&lt;br /&gt;
 01000 ! Replace Envdb&lt;br /&gt;
 01020    dim DATABASES$(1)*100&lt;br /&gt;
 01040    dim DATABASE$*100&lt;br /&gt;
 01060    dim TABLES$(1)*100&lt;br /&gt;
 01080    dim TABLE$*100&lt;br /&gt;
 01100    dim COLUMNS$(1)*100&lt;br /&gt;
 01120    dim COLUMN$*100&lt;br /&gt;
 01140    dim C$*100,FLD1$*40,FLD2$*40,FLD3$*40,FLD4$*40&lt;br /&gt;
 01160    execute &amp;quot;CONFIG database testdb odbc-manager&amp;quot;&lt;br /&gt;
 01180 !   Execute &amp;quot;CONFIG database testdb DSN=&#039;Accounts Payable&#039;&amp;quot;&lt;br /&gt;
 01220 !   Execute &amp;quot;CONFIG database testdb connectstring=&amp;quot;&amp;quot;DSN=Excel Files;DBQ=L:\orders\Beneficial - A-PORCEL.xls;DefaultDir=L:\orders;DriverId=1046;MaxBufferSize=2048&amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
 01230 ! *****  Open Output File&lt;br /&gt;
 01240    open #1: &amp;quot;name=envdb.txt,replace&amp;quot;,display,output &lt;br /&gt;
 01420 Dump_Table: ! ***** Dump Table Layout&lt;br /&gt;
 01440    let OUTFD = 1&lt;br /&gt;
 01460    let ENV$(&amp;quot;status.database.LIST&amp;quot;, MAT DATABASES$)  !List of db&#039;s&lt;br /&gt;
 01480    for DATABASE=1 to UDIM(DATABASES$)  !For each connected database&lt;br /&gt;
 01500       let DATABASE$=DATABASES$(DATABASE)&lt;br /&gt;
 01520       let FNSHOW_DATABASE(DATABASE$, &amp;quot;status.database.&amp;quot;&amp;amp;DATABASE$)&lt;br /&gt;
 01540    next DATABASE&lt;br /&gt;
 01560    end &lt;br /&gt;
 01580 ! &lt;br /&gt;
 01600    def FNSHOW_DATABASE(DATABASE$*100, ST_PREFIX$*100)&lt;br /&gt;
 01620       print #OUTFD: DATABASE$&lt;br /&gt;
 01640       let OUT_PREFIX$=CHR$(9)&lt;br /&gt;
 01660       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;DSN=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DSN&amp;quot;)&lt;br /&gt;
 01680       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;CONNECTSTRING=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.CONNECTSTRING&amp;quot;)&lt;br /&gt;
 01700       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Tables:&amp;quot;&lt;br /&gt;
 01720       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.TABLES&amp;quot;&lt;br /&gt;
 01740       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT TABLES$)&lt;br /&gt;
 01760       for TABLE = 1 to UDIM(MAT TABLES$)&lt;br /&gt;
 01780          let TABLE$=TABLES$(TABLE)&lt;br /&gt;
 01800          let FNSHOW_TABLE(TABLE$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;TABLE$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 01820       next TABLE&lt;br /&gt;
 01840    fnend &lt;br /&gt;
 01860 ! &lt;br /&gt;
 01880    def FNSHOW_TABLE(TABLE$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 01900       print #OUTFD: OUT_PREFIX$&amp;amp;TABLE$&lt;br /&gt;
 01920       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 01940       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table remarks=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.REMARKS&amp;quot;)&lt;br /&gt;
 01960       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Table type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 01980       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Columns:&amp;quot;&lt;br /&gt;
 02000       let ST_PREFIX$=ST_PREFIX$&amp;amp;&amp;quot;.COLUMNS&amp;quot;&lt;br /&gt;
 02020       let ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LIST&amp;quot;, MAT COLUMNS$)&lt;br /&gt;
 02040       for COLUMN = 1 to UDIM(MAT COLUMNS$)&lt;br /&gt;
 02060          let COLUMN$=COLUMNS$(COLUMN)&lt;br /&gt;
 02080          let FNSHOW_COLUMN(COLUMN$, ST_PREFIX$&amp;amp;&amp;quot;.&amp;quot;&amp;amp;COLUMN$,OUT_PREFIX$&amp;amp;CHR$(9))&lt;br /&gt;
 02100       next COLUMN&lt;br /&gt;
 02120    fnend &lt;br /&gt;
 02140 ! &lt;br /&gt;
 02160    def FNSHOW_COLUMN(COLUMN$*100, ST_PREFIX$*100, OUT_PREFIX$)&lt;br /&gt;
 02180       print #OUTFD: OUT_PREFIX$&amp;amp;COLUMN$&lt;br /&gt;
 02200       let OUT_PREFIX$=OUT_PREFIX$&amp;amp;CHR$(9)&lt;br /&gt;
 02220       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column type=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.TYPE&amp;quot;)&lt;br /&gt;
 02240       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column length=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.LENGTH&amp;quot;)&lt;br /&gt;
 02260       print #OUTFD: OUT_PREFIX$&amp;amp;&amp;quot;Column decimals=&amp;quot;&amp;amp;ENV$(ST_PREFIX$&amp;amp;&amp;quot;.DECIMALS&amp;quot;)&lt;br /&gt;
 02280    fnend&lt;br /&gt;
&lt;br /&gt;
==  BR DATA ENCRYPTION==&lt;br /&gt;
&lt;br /&gt;
Encryption encompasses a number of different operations.  These operations can be used independently or in combination to meet different needs.  We use industry standard encryption available through OpenSSL.  Three technologies are widely used for encrypting data. BR supports the first two listed below through its ENCRYPT and DECRYPT functions. &lt;br /&gt;
&lt;br /&gt;
===Overview===&lt;br /&gt;
&lt;br /&gt;
1. Symmetric key ciphers – where the same key is used to encrypt and decrypt data.  You can specify a key to encrypt some data and later use the same key to decrypt the data.&lt;br /&gt;
&lt;br /&gt;
2. Hashing routines – one way routines that take data and convert it to a hash value.  Sometimes these are thought of as checksums such as MD5 sum.  Hash values are always the same length regardless of how big the hashed data is.  A 10 gb file will have a hash result that is the same length as a 200 byte file.  Hashing routines have a number of specific uses.&lt;br /&gt;
&lt;br /&gt;
1. Verify that data has not changed.&lt;br /&gt;
&lt;br /&gt;
2. Verifying that two files are the same.&lt;br /&gt;
&lt;br /&gt;
3. Validating passwords – this is based on the concept that if two values have the same hash value the values are equal.  Using this technique improves security because it allows a server to store passwords in an unrecoverable format.  Even the server software is unable to regenerate the original password.  It is only capable of checking if the hash of a password matches the stored password hash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Symmetric Key Ciphers===&lt;br /&gt;
&lt;br /&gt;
There are two encryption functions in the BR language, ENCRYPT$ and DECRYPT$.&lt;br /&gt;
&lt;br /&gt;
 ENCRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
 DECRYPT$(Data$ [,Key$ [,Encryption-type$, [,Initialization-vector$]]])&lt;br /&gt;
&lt;br /&gt;
Data$ - The data to be encrypted&lt;br /&gt;
&lt;br /&gt;
Key$ - The secret key to be used for encryption.  If not specified this value will come from an OPTION 66 statement.&lt;br /&gt;
&lt;br /&gt;
Encryption-type$ - The type of encryption to be done.  If not specified, a common high strength encryption type will be employed.  This is described in more detail below, but is generally only useful for interfacing with other typically non-BR programs.&lt;br /&gt;
&lt;br /&gt;
Initialization-vector$ - This is an arcane part of encryption standards.  It exists to prevent attackers from being able to tell whether the unencrypted data has changed.  This is described in more detail below, but is general only needed when interfacing with other non-BR programs.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Interfacing With Other Programs (encryption type and initialization vector)===&lt;br /&gt;
&lt;br /&gt;
There are a number of different types of encryption that BR supports through OpenSSL:  AES, BLOWFISH, DES, triple DES, RC4 and RC2.  Most symmetric key ciphers are block ciphers meaning that they encrypt one block at a time.  This means if you have a bit message, it is broken up into multiple blocks and each block is encrypted.  The block size can be set as (128, 192, 256) bits.  Some encryption types don&#039;t support all of these values so STATUS ENCRYPTION should be checked to see what encryption types are available in BR.  Besides block size, there are also various schemes for blocking data.  One might expect that using 256 bit blocking would simply take every 32 bytes and call it a block.  This is not done though because there is a possibility that this would cause patterns in the encrypted data.  To prevent this, there are various schemes known as codebooks which change the way data is blocked.  Wikipedia explains this in more detail.  If the encryption type is not specified AES:256:CBC:128 will be used.  To be compatible with other programs the entire encryption type must be specified (cipher: key length: codebook: invitialization vector length).&lt;br /&gt;
&lt;br /&gt;
Initialization-vector – this is used to cause the same data encrypted with the same key to have a different encrypted result.  This is significant because otherwise an attacker looking at data seeing the same encrypted result twice would know that the key and the unencrypted data have not changed.  Regardless of whether or not you are concerned about this potential security issue, the standard encryption methods require this value so interfacing with other programs may require you to use it.  It is a common practice to use a random number for this value and store the value at the beginning of (ahead of) the encrypted result.  This is what BR does if this parameter is omitted.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
 ENCRYPT$(“test”, “key”) &lt;br /&gt;
Produces a string containing “random number initialization vector”&amp;amp;”encrypted result”.&lt;br /&gt;
&lt;br /&gt;
If the initialization vector is explicitly specified as in:&lt;br /&gt;
ENCRYPT$(“test”, “key”, “AES:256:CBC:128”, “RANDOM”) &lt;br /&gt;
the result would be simply “encrypted result”.&lt;br /&gt;
&lt;br /&gt;
DECRYPT$ has the same arguments as ENCRYPT$ with the exception of the first parameter which is the encrypted data.  DECRYPT$ expects to be used with the same key$, encryption-type$, and initialization-vector$ as was used to encrypt the data.  As with ENCRYPT$, if key$ is not specified, the value from the OPTION statement will be used.  If encryption-type$ is not specified, “AES:256:CBC:128” will be used.  If the initialization vector is not specified, it will be assumed that the encrypted data starts with an initialization vector.&lt;br /&gt;
&lt;br /&gt;
=== Hashing Routines===&lt;br /&gt;
&lt;br /&gt;
Three common forms of hashing are allowed in BR.  They are MD5, SHA, and SHA-1.  These are also provided through the ENCRYPT$ function specifying a null key$ value:&lt;br /&gt;
&lt;br /&gt;
ENCRYPT$(data$, “”, “MD5”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA”)&lt;br /&gt;
ENCRYPT$(data$, “”, “SHA-1”)&lt;br /&gt;
&lt;br /&gt;
Hashing is also referred to as Message Digests or digests.  This is what the MD in MD5 means.  There is no way to restore data that has been hashed.   Hashing is a one way function so DECRYPT$ will yield an error.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Asymmetric Encryption===&lt;br /&gt;
&lt;br /&gt;
Asymmetric key encryption is also known as public/private key encryption. &lt;br /&gt;
&lt;br /&gt;
Public/private keys are created as a pair by a key generator.  They are a pair, and it is not possible to have two public keys for the same private key or vice versa.   With regard to public/private key pairs, what one key encrypts the other key can decrypt, and neither key can decrypt what it has encrypted.  When a private key is used to encrypt data, the result is called a signature because everyone who has the public key can decrypt it.&lt;br /&gt;
&lt;br /&gt;
This technique is used for:&lt;br /&gt;
&lt;br /&gt;
Signing (using certificates) – A private key can be used to sign data.  The result of such signing can be tested/validated with the corresponding public key. &lt;br /&gt;
&lt;br /&gt;
Data encryption – A public key can be used to encrypt data.  This data can then only be decrypted by the corresponding private key. &lt;br /&gt;
&lt;br /&gt;
Hashes and signing are different but used together.  Rather than signing a large block of data which would create a large signature, only the hash is signed to create much smaller fixed length signature data.  When verifying a large block of signed data, the data is used to create a hash value and the hash value is compared to a decrypted signature.&lt;br /&gt;
&lt;br /&gt;
Asymmetric encryption is not accessible through the BR ENCRYPT$, DECRYPT$ functions.  However, it is used by our SSL client server connections and HTTPS.  Certificates are most commonly used by SSL and HTTPS and are less useful for other application processes. In the Client Server model the client knows the server’s public key and the server uses its private key to encrypt and decrypt.&lt;br /&gt;
&lt;br /&gt;
Encryption is invoked by Business Rules HTTP support as follows:&lt;br /&gt;
&lt;br /&gt;
 CONFIG HTTPS port-number   [ LOG file-pathname ] [CERT= cert-file-basename]&lt;br /&gt;
 CONFIG OPTION  66   private-key-file-encryption-password&lt;br /&gt;
 OPEN #400: “HTTP=SERVER”, DISPLAY, OUTIN&lt;br /&gt;
&lt;br /&gt;
The BRSERVER executable directory must contain two files: &lt;br /&gt;
* https-private.pem&lt;br /&gt;
* https-cert.pem&lt;br /&gt;
&lt;br /&gt;
These files are made by the following commands under Linux, MAC and cygwin for Windows:&lt;br /&gt;
openssl req -new -x509 -out httpserver.pem -days 10000&lt;br /&gt;
&lt;br /&gt;
( this will prompt for the OPTION 66 password )&lt;br /&gt;
&lt;br /&gt;
 mv privkey.pem   https-private.pem&lt;br /&gt;
 mv httpserver.pem   https-cert.pem&lt;br /&gt;
&lt;br /&gt;
This port specific service can then be accessed with browsers. When the specified port is accessed through a browser, BR establishes an HTTPS connection rather than an HTTP connection.&lt;br /&gt;
&lt;br /&gt;
=== Signing and Certificate Processing Industry Standards===&lt;br /&gt;
&lt;br /&gt;
Certain companies are authorized by the government to act as a Certificate Authority ( CA ). These companies ( e.g. Verisign ) issue electronic certificates which can be used to issue second level certificates. Certificates can have expiration dates and the line of authority extends from a CA to any number of levels (but a chain is only as strong as its weakest link). Certificates contain a list of signatures (described below) that trace back to a CA as follows: &lt;br /&gt;
&lt;br /&gt;
When a company needs to obtain a certificate from a CA, it prepares its own certificate and sends it to the CA for signature. The CA provides the signature and the CA’s own public key for validating it. The text in such certificates will identify the signing authority ( CA ) and the recipient of the certificate. It also contains the public key of both the signer and the recipient. &lt;br /&gt;
&lt;br /&gt;
Browsers know the CA identities and their public keys. A browser can verify a CA issued cert by hashing it, decrypting the signature with the known public key and matching the decrypted signature against the hash total. &lt;br /&gt;
 &lt;br /&gt;
Any company that is issued a certificate by a CA can sign second level certificates issued to third parties. A second level cert contains the parent (CA issued) certificate, and includes the public keys of the issuer and the recipient. The signature is essentially the encrypted hash total of ‘itself plus all of its ancestors’. Additional levels each contain the chain of certificates leading from a CA issued cert to itself. &lt;br /&gt;
&lt;br /&gt;
Ostensibly, a certificate cannot be counterfeited because it requires the signature of its parent which can only be produced with its parent’s private key.  By providing both public keys ( signer and recipient ) in all certs along with signatures, a non-forgeable or alterable chain is established. &lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
CA public key – known to browser&lt;br /&gt;
certificate 1 (signed by CA)&lt;br /&gt;
certificate 2 (signed by second level - includes certificate 1)&lt;br /&gt;
final certificate (signed by third level - includes certificate 2)&lt;br /&gt;
 &lt;br /&gt;
A browser would find the CA information in the certificate and check to see if it is in the browser’s internal list.  If not it fails.  Then it verifies that certificate 1 (which ends up being part of the final certificate) has been signed by the CA.  After that it checks certificate 2 and verifies that it has been signed with certificate 1.  Finally it checks the final certificate and verifies that it has been signed with certificate 2.&lt;br /&gt;
 &lt;br /&gt;
To assure the line authority of any certificate, the public keys are associated with signers, not with documents.&lt;br /&gt;
&lt;br /&gt;
== ODBC VERSION 4.3==&lt;br /&gt;
&lt;br /&gt;
Improved installation routines:&lt;br /&gt;
Easy to use&lt;br /&gt;
Compatible with Windows Vista/7&lt;br /&gt;
Compatible with 64 Bit Machines (both 32 and 64 bit drivers).&lt;br /&gt;
Easily create DNS entries from the CONTEXT using a BR program called CREATE_INI.BR. (You will need to tailor the resulting INI file to the target setting.)&lt;br /&gt;
Installation on a client can be done from a command line avoiding the need for human interaction at the client. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Support for 64 bit Record Locking (No 2GB Limit!).&lt;br /&gt;
Implemented Dynamic (on the fly) Indexes.&lt;br /&gt;
The ODBC splash screen has been removed.&lt;br /&gt;
&lt;br /&gt;
ODBC Logging:&lt;br /&gt;
*Set Logging to level 6 or greater.&lt;br /&gt;
*LOGGING 6, C:\ODBC-LOG.TXT&lt;br /&gt;
*Log file will provide helpful information to analyze queries.&lt;br /&gt;
*Actual SQL processed by Driver (As opposed to the SQL typed in MS-Access or MS-Excel)&lt;br /&gt;
*Indexes used by the Query. (To help determine the &amp;quot;BEST Query&amp;quot; for performance).&lt;br /&gt;
&lt;br /&gt;
More Robust:&lt;br /&gt;
*Improved Date Handling (Sort/Filter, etc).&lt;br /&gt;
*Improved Joins leverage &amp;amp;/or create indexes for performance.&lt;br /&gt;
*Improved Group By queries&lt;br /&gt;
*Improved &amp;quot;Like&amp;quot; filters.&lt;br /&gt;
*Improved Multiple Filters in a single query&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== ODBC Licensing And Security===&lt;br /&gt;
&lt;br /&gt;
Licenses will be issued based on number of workstations or number of BR WSIDs.&lt;br /&gt;
&lt;br /&gt;
The price per user for licensing based on the number of BR WSIDs is one half of the price based on the number of ODBC workstations. &lt;br /&gt;
&lt;br /&gt;
The maximum license fee for ODBC is $4900.&lt;br /&gt;
&lt;br /&gt;
====Enforcement====&lt;br /&gt;
If the ODBC license is based on the number of BR users, then the BRSERIAL.DAT file always specifies 999 users. &lt;br /&gt;
&lt;br /&gt;
We assign a random number to each machine that uses the ODBC driver and another random number to each user of ODBC. These numbers are stored along with the date, encrypted in a table in the server and client registries.  Each time a session is started, the client is checked for pre-existing control numbers and if they exist then the numbers are used for the session (along with the current date). If a client reports a pre-existing number less than 14 days old that is not in the server table, then an alarm is signaled. This indicates tampering with the server table.&lt;br /&gt;
&lt;br /&gt;
When a control number pair is about to be added to the server table and the table is full then it is searched for an entry more than 14 days old for replacement. If no such entry exists, then a “maximum users exceeded” error message is presented. &lt;br /&gt;
&lt;br /&gt;
When a computer is replaced, this can leave an unusable entry in the server table for up to 14 days. If this occurs, then the user can run a program on the server that writes an encrypted header with the current date to the server table indicating that the table has been cleared in a licensed manner.  After this has been run, all entries in the table will be available for reuse.  Clients that have pre-existing control numbers will not generate the tamper error when the license file is cleared in this manner unless the client last used date is greater than the encrypted header date. This program requires a password which is an encrypted form of the current date plus the serial number. Only the dealer has the password producing program so only the dealer can obtain the current day’s password. &lt;br /&gt;
&lt;br /&gt;
When a client machine has more than two ODBC user entries, the entries greater than&lt;br /&gt;
one are counted as separate workstations. e.g. 1 or 2 -&amp;gt;1, 3-&amp;gt;2, 4-&amp;gt;3, etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== New Procedure for Utilizing MS Access ODBC Middleware ===&lt;br /&gt;
&lt;br /&gt;
A procedure has been established for greatly expanding the SQL capabilities of the BR ODBC driver by routing ODBC requests through MS Access. Using this technique one can create reusable queries that combine several tables. This procedure is described in the installation guide. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  PRINT FONT STRETCHING==&lt;br /&gt;
&lt;br /&gt;
When we developed the PDF printing facility we encountered a problem getting PDF to print exactly like NWP and PCL.  This was partly because early in NWP development we stretched the fixed width fonts vertically for maximum legibility. So in version 4.2 we adopted a default font that was more like PCL that we could print in both NWP and PDF.&lt;br /&gt;
&lt;br /&gt;
However, we eventually returned to the older stretched fonts because of their superior legibility. This issue affects only fixed width fonts. This stretching can be disabled with OPTION 68. &lt;br /&gt;
&lt;br /&gt;
We are now using Courier New as the default font.  pdflib4-Win32.dll adds support for this stretching to our PDF capabilities.&lt;br /&gt;
&lt;br /&gt;
Relative Font Heights ( height to width ratios ):&lt;br /&gt;
    Native Courier New  1.6 		- available in PCL -&lt;br /&gt;
    Native Letter Gothic  2.0		- available in PCL -&lt;br /&gt;
    Stretched Fonts 2.6		- NWP and PDF only -&lt;br /&gt;
&lt;br /&gt;
The 1.6, 2.0, 2.6 are ratios.  For Courier New the 1.6 means that the font is 1.6 times as high as it is wide.  PCL measures all fixed width fonts in width and calculates the height based on these ratios.  So for Courier New a 10 CPI font would be 1.6 * (1 / 10)(CPI) * 72 (points per inch) = 11.52 points.  Actually the ratio for Courier New appears to be 1.66666666.  This would mean that 1.66666666 * (1/10) * 72 = 12 points.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  EXTENDED DATE / TIME FUNCTIONS==&lt;br /&gt;
&lt;br /&gt;
Date numeric variables can now represent time of day in the fractional space (to the right of the decimal point). The DAYS and DATE masks have been extended as follows:&lt;br /&gt;
&lt;br /&gt;
H#.## or H denotes hours [ with fractions ].&lt;br /&gt;
M#.### or M#.# denotes minutes.&lt;br /&gt;
S#.####, S or S# denotes seconds.&lt;br /&gt;
&lt;br /&gt;
M, to the right of H always denotes minutes, so H:M:S is sufficient.&lt;br /&gt;
Either AM or PM, to the right of H denotes AM / PM output.&lt;br /&gt;
The absence of AM and PM denote military hours (0 – 23).&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
Extended Date Mask Examples:&lt;br /&gt;
 DATE( “Month dd, ccyy at H#.## hours”)  -&amp;gt;  September 12, 2011 at 14.58 hours&lt;br /&gt;
 DATE( “mm/dd/yy at H:M AM”)  -&amp;gt;  09/15/11 at 2:35 PM&lt;br /&gt;
 DATE( “mon dd cy at H#:M# PM”)  -&amp;gt;  Sep 15 2011 at 02:35 PM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Example of using DATE$ to get time to 9 decimal places:&lt;br /&gt;
 Date$(&amp;quot;H#:M#:S#.#########&amp;quot;) -&amp;gt; 14:06:22.968419347&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
When storing date/time combinations on disk, you should allow for all of the significant digits that your date mask supports on each side of the decimal point. A “BH 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, PD 7, PD 8 or D 8 (double floating point) to store these values on disk.  DATE() only works with day-of-century values along with an optional time fraction.&lt;br /&gt;
&lt;br /&gt;
==  NEW DATE MASK INPUT PROCESSING==&lt;br /&gt;
&lt;br /&gt;
DATE(mask) can now be used as an INPUT FIELDS specification.&lt;br /&gt;
&lt;br /&gt;
10 INPUT FIELDS “row, col, DATE(mask)  ,UH” : date-var&lt;br /&gt;
&lt;br /&gt;
Special keyboard processing:&lt;br /&gt;
Punctuation (commas, colons, slashes, semicolons, and dashes) is skipped during entry similar to PIC.&lt;br /&gt;
Insert and delete are supported within subfields that are delineated by punctuation.&lt;br /&gt;
Copy includes punctuation.&lt;br /&gt;
Cut is Copy with redisplay of zero date.&lt;br /&gt;
Paste causes BR to translate the date to DAYS format and then display the date. Excel and OpenOffice Calc application formats are supported.&lt;br /&gt;
If a string is pasted, it is first converted to DAYS using the provided mask.&lt;br /&gt;
If a zero DAYS value is displayed then Month, M3, Day and D3 mask positions contain dashes.&lt;br /&gt;
&lt;br /&gt;
A date picker has been added. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A new configuration statement is provided to control the when the date picker appears:&lt;br /&gt;
&lt;br /&gt;
DATE   [ALWAYS]  [INVALID]  [NEVER]&lt;br /&gt;
&lt;br /&gt;
Additionally, the leading attribute ^DATE_PICKER is available.&lt;br /&gt;
&lt;br /&gt;
INVALID ( the default mode ) presents the date picker whenever the days value of the expressed date is zero.&lt;br /&gt;
&lt;br /&gt;
ALWAYS and ^DATE_PICKER 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. &lt;br /&gt;
&lt;br /&gt;
When in the date picker the following keys are active:&lt;br /&gt;
Shift- PgUp/PgDn – Go to the previous/next month&lt;br /&gt;
Ctrl- PgUp/PgDn – Go to the previous/next year&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate date entry is:&lt;br /&gt;
01000 ! Rep Date_Input&lt;br /&gt;
01020 ! Demonstrate The New Date() Input Format&lt;br /&gt;
01040 ! Skip Punctuation (Commas, Colons, Slashes, Semicolons, And Dashes)&lt;br /&gt;
01060 ! Insert And Delete Within Subfields That Are Delineated By Punctuation&lt;br /&gt;
01080 ! Continue To Support Cut And Paste Including Punctuation&lt;br /&gt;
01100 ! &lt;br /&gt;
01120    rinput fields &amp;quot;5,10,DATE(mm/dd/yy) ;6,10,c&amp;quot;: DATE_VAR&lt;br /&gt;
01140    print fields &amp;quot;8,10,date(Month DD, CCYY)&amp;quot;: DATE_VAR&lt;br /&gt;
01160 ! &lt;br /&gt;
01180    rinput fields &amp;quot;12,10,date(month dd, ccyy)&amp;quot;: DATE_VAR&lt;br /&gt;
01200    if NOT DATE_VAR then goto 1180&lt;br /&gt;
01220    print fields &amp;quot;15,10,date(yy/mm/dd)&amp;quot;: DATE_VAR &lt;br /&gt;
01240    print fields &amp;quot;18,10,N 6&amp;quot;: DATE_VAR  !Show days format&lt;br /&gt;
&lt;br /&gt;
         &lt;br /&gt;
&lt;br /&gt;
==  NEW TEXT FIELD FORMAT==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS “row, col, TEXT rows/cols[/capacity],  leading-attr,  …”:&lt;br /&gt;
&lt;br /&gt;
This format is similar to the C/V/G format with the ^ENTER_LF attribute except:&lt;br /&gt;
No trailing space padding or trimming occurs.&lt;br /&gt;
Rows and columns are specified.&lt;br /&gt;
Field capacity or newlines can cause a vertical scrollbar to appear.&lt;br /&gt;
&lt;br /&gt;
Supported leading attributes are ^ENTER_LF (the default), ^ENTER_CRLF and ^NOWRAP.&lt;br /&gt;
The TEXT keyword will imply ^ENTER_LF unless ^ENTER_CRLF is specified.&lt;br /&gt;
&lt;br /&gt;
^ENTER_LF (the default) causes the ENTER key to add LF characters to the data and to go to a new line left justified. The cursor will retrace the data when backspace or left-arrow is keyed, meaning the on-screen LF characters are represented by moving the cursor, instead of allowing it to rest on invisible LF characters.&lt;br /&gt;
&lt;br /&gt;
^ENTER_CRLF may be specified in lieu of ^ENTER_LF. When that is the case, carriage returns entered are represented in the data as carriage-return-linefeed (CRLF) character pairs.  ^NOWRAP may be specified to suppress word wrapping. When ^NOWRAP is active, data is entered on the current line until ENTER is keyed to go to the next line. Both horizontal and vertical scroll bars appear as needed.&lt;br /&gt;
&lt;br /&gt;
Tabs are entered into the text. Shift-tab is ignored.&lt;br /&gt;
&lt;br /&gt;
Home, End and the arrow keys all operate relative to the current line as opposed to operating on the text box as a whole.&lt;br /&gt;
&lt;br /&gt;
Depressing the Control key causes the following keys to operate in the normal string entry mode:&lt;br /&gt;
&lt;br /&gt;
*Enter – Returns control to the BR program&lt;br /&gt;
*Tab – Goes to the next control&lt;br /&gt;
*Shift-Tab – Goes to the prior control&lt;br /&gt;
*Home – Goes to the beginning of data or the first field&lt;br /&gt;
*End – Goes to the end of data or the last field&lt;br /&gt;
*Left-Arrow/Up-Arrow – Goes to the prior control&lt;br /&gt;
*Right-Arrow/Down-Arrow – Goes to the next control&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[CurPos]] introduced.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A sample program to demonstrate TEXT entry is:&lt;br /&gt;
 01000 ! Rep Text&lt;br /&gt;
 01020 ! Test New Text Fiueld Type&lt;br /&gt;
 01040    dim TEXT$*300, TEXT$(1)*80&lt;br /&gt;
 01060    print NEWPAGE&lt;br /&gt;
 01080    rinput fields &amp;quot;3,10,text 4/40/300,uh&amp;quot;: TEXT$&lt;br /&gt;
 01100    print fields &amp;quot;10,10,c&amp;quot;: TEXT$&lt;br /&gt;
 01120    print TEXT$&lt;br /&gt;
 01140    let STR2MAT(TEXT$, MAT TEXT$, CHR$(10))&lt;br /&gt;
 1160 rint MAT TEXT$&lt;br /&gt;
&lt;br /&gt;
==  INPUT ACROSS MULTIPLE WINDOWS==&lt;br /&gt;
&lt;br /&gt;
10  (R)INPUT FIELDS  #121: “10, 10, C 20, UH; 10, 12, PIC(##/##/##), UH;#124,&lt;br /&gt;
10, 10, C 30, UH”: aaa$, bbb$, ccc$&lt;br /&gt;
&lt;br /&gt;
This will input the first two fields on window #121 and the third field on window #124.  The ‘#window-number,’ prefix may appear in any row, col FIELDS specification and it overrides the window number that follows the PRINT/INPUT/RINPUT keyword. &lt;br /&gt;
&lt;br /&gt;
== CONFIG CONSOLE CHANGES==&lt;br /&gt;
&lt;br /&gt;
[[Console]] [[BRConfig.sys]] specification  introduced.&lt;br /&gt;
&lt;br /&gt;
==  BR IN A BROWSER==&lt;br /&gt;
&lt;br /&gt;
We have made it easy to setup BR in a Browser once you have Client Server working. &lt;br /&gt;
Point your browser at ads.net/plugin for a demonstration. Located in that directory is a file called index.html which is also on the FTP site in the BETA release browser-plugin directory.  Modify this file to setup your own web page. &lt;br /&gt;
&lt;br /&gt;
This HTML file demonstrates activation of BR client server in a browser. It first checks to see if the plugin is installed and if not it installs it. If needed, it updates the plugin from the ads.net site. It then initiates a connection to the server just like the BR client does. See the HTML file for further instructions, including how to confine BR to a window on the launch page if desired. &lt;br /&gt;
&lt;br /&gt;
A new OPTION 70 is provided which will default to being ON in the Browser version.  OPTION 70 will do the same thing as 54 (exit if BR enters command console mode), but it will be configurable to:&lt;br /&gt;
OPTION 70 OFF		! This can be set programmatically&lt;br /&gt;
OPTION 70 ON		! Same as OPTION 54 – the default for browsers&lt;br /&gt;
OPTION 70 RELAXED	! Mild security – enables some support&lt;br /&gt;
 &lt;br /&gt;
RELAXED mode is intended to allow some debugging but still provide some security.  This means disabling commands such as COPY, DIR, etc., CONFIG commands, and preventing changes from being made to BR programs. However, the security can be defeated  because all of these activities can be performed by programs or procedures. Use ON (the default) for high security. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==  NEW AND CHANGED ERROR CODES==&lt;br /&gt;
* [[0000]] Successful completion no error&lt;br /&gt;
* [[0050]] Writing to BTREE2 file failed&lt;br /&gt;
* [[0059]] DEPRECATED ERROR: attempt to rewrite over key&lt;br /&gt;
* [[0063]] DEPRECATED ERROR: network locking error&lt;br /&gt;
* [[0417]] MSG string it too long&lt;br /&gt;
* [[0419]] Invalid MSG special char specification&lt;br /&gt;
* [[0436]] Bad flags for MAT2STR or STR2MAT&lt;br /&gt;
* [[0620]] DEPRECATED ERROR: duplicate OPEN for standard printer output&lt;br /&gt;
* [[0641]] DEPRECATED ERROR: missing protection device &lt;br /&gt;
* [[0635]] Error using SSL socket&lt;br /&gt;
* [[0717]] Error deleting record from BTREE2 file&lt;br /&gt;
* [[0727]] DEPRECATED ERROR: FORM variable not referenced&lt;br /&gt;
* [[0807]] Border characters can no longer be specified&lt;br /&gt;
* [[0814]] Bad or missing trailing attribute&lt;br /&gt;
* [[0818]] DEPRECATED ERROR: number too large for PIC format&lt;br /&gt;
* [[0865]] DEPRECATED ERROR: invalid attribute combination&lt;br /&gt;
* [[0887]] Sort column is not valid&lt;br /&gt;
* [[0930]] INPUT FIELDS &amp;quot;...RANGE&amp;quot; bad range variables&lt;br /&gt;
* [[0931]] Invalid insert or delete change with range&lt;br /&gt;
* [[0940]] Value does not match boolean format&lt;br /&gt;
* [[0941]] NULL boolean value used where allow null is false&lt;br /&gt;
* [[0945]] The length of the date format is excessively long&lt;br /&gt;
* [[1008]] Invalid keyword in shell interpreter&lt;br /&gt;
* [[1033]] Scalar variable in an array group&lt;br /&gt;
* [[2022]] The given encryption method does not exist&lt;br /&gt;
* [[2024]] The encryption method is only valid one way&lt;br /&gt;
* [[2026]] Missing encryption key&lt;br /&gt;
* [[2030]] Failed processing encryption&lt;br /&gt;
* [[2070]] DEPRECATED ERROR: not enough memory&lt;br /&gt;
* [[2080]] DEPRECATED ERROR: insufficient dimensioned storage&lt;br /&gt;
* [[2090]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2100]] Too many active procedures&lt;br /&gt;
* [[2101]] Illegal line number&lt;br /&gt;
* [[2102]] GO attempted without running program&lt;br /&gt;
* [[2103]] Illegal PROC parameter&lt;br /&gt;
* [[2104]] No active lines to run&lt;br /&gt;
* [[2108]] Program is active&lt;br /&gt;
* [[2109]] No program in memory to SAVE or REPLACE&lt;br /&gt;
* [[2111]] Missing lines for a program in object code&lt;br /&gt;
* [[2116]] Cannot SAVE during LOAD or MERGE&lt;br /&gt;
* [[2120]] DEPRECATED ERROR: not enough compilation storage&lt;br /&gt;
* [[2130]] Program changed since LOAD at another workstation&lt;br /&gt;
* [[3031]] DEPRECATED ERROR: 0 bytes available on disk&lt;br /&gt;
&lt;br /&gt;
* [[4002]] SQL create statement failed&lt;br /&gt;
* [[4003]] SQL free statement failed&lt;br /&gt;
* [[4004]] SQL prepare failed&lt;br /&gt;
* [[4005]] SQL clear old results failed&lt;br /&gt;
* [[4006]] SQL execute direct failed&lt;br /&gt;
* [[4007]] WRITE to SQL with incorrect number of data elements&lt;br /&gt;
* [[4008]] SQL describe result set columns failed&lt;br /&gt;
* [[4009]] SQL bind result set columns failed&lt;br /&gt;
* [[4010]] SQL fetch row failed&lt;br /&gt;
* [[4011]] SQL bind parameter failure&lt;br /&gt;
* [[4012]] Prepared SQL execution failure&lt;br /&gt;
* [[4014]] Error converting time stamp to string value or back&lt;br /&gt;
&lt;br /&gt;
* [[4114]] DEPRECATED ERROR: invalid disk or disk drive reference&lt;br /&gt;
* [[4115]] The specified database has not been opened&lt;br /&gt;
* [[4120]] Invalid Y2K data found in an index field&lt;br /&gt;
* [[4121]] DEPRECATED ERROR: invalid use of key file&lt;br /&gt;
* [[4123]] Corrupted BTREE index&lt;br /&gt;
* [[4128]] DEPRECATED ERROR: invalid file name&lt;br /&gt;
* [[4135]] DEPRECATED ERROR: volume ID invalid&lt;br /&gt;
* [[4137]] DEPRECATED ERROR: not enough storage space to create file&lt;br /&gt;
* [[4138]] Can&#039;t rename between client and server&lt;br /&gt;
* [[4140]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4141]] DEPRECATED ERROR: shared memory problem&lt;br /&gt;
* [[4142]] DEPRECATED ERROR: too many opened file names&lt;br /&gt;
* [[4143]] DEPRECATED ERROR: out of shared memory&lt;br /&gt;
* [[4144]] DEPRECATED ERROR: network semaphore error&lt;br /&gt;
* [[4145]] Time out while waiting for input from user or ASYNC file I/O&lt;br /&gt;
* [[4147]] A file has been opened too many times at the share level&lt;br /&gt;
* [[4149]] Different version of BR running with locking&lt;br /&gt;
* [[4159]] DEPRECATED ERROR: volume not on line&lt;br /&gt;
* [[4160]] Out of internal file handles&lt;br /&gt;
* [[4174]] Attempted file reservation on non-local file&lt;br /&gt;
* [[4175]] Multiple wbserver files detected&lt;br /&gt;
* [[4177]] DEPRECATED ERROR: windows shell call without command&lt;br /&gt;
* [[4179]] Failed to lock in progress on wbserver.dat&lt;br /&gt;
* [[4180]] Bad drive statement&lt;br /&gt;
* [[4185]] Setting the directory failed on the client side&lt;br /&gt;
* [[4194]] REWRITE check for null bytes failed&lt;br /&gt;
* [[4195]] READ check for null bytes failed&lt;br /&gt;
* [[4196]] WRITE check for null bytes failed&lt;br /&gt;
&lt;br /&gt;
* [[4200]] DEPRECATED ERROR: DOS/Windows/Novell error 0&lt;br /&gt;
* [[4201]] DEPRECATED ERROR: DOS/Windows/Novell error 1&lt;br /&gt;
* [[4202]] DEPRECATED ERROR: DOS/Windows/Novell error 2&lt;br /&gt;
* [[4203]] Path does not exist or is not a directory&lt;br /&gt;
* [[4204]] Too many file handles open on the system level&lt;br /&gt;
* [[4205]] Access is denied&lt;br /&gt;
* [[4206]] Invalid file descriptor&lt;br /&gt;
* [[4207]] DEPRECATED ERROR: DOS/Windows/Novell error 7&lt;br /&gt;
* [[4208]] DEPRECATED ERROR: DOS/Windows/Novell error 8&lt;br /&gt;
* [[4209]] DEPRECATED ERROR: DOS/Windows/Novell error 9&lt;br /&gt;
* [[4210]] DEPRECATED ERROR: DOS/Windows/Novell error 10&lt;br /&gt;
* [[4211]] DEPRECATED ERROR: DOS/Windows/Novell error 11&lt;br /&gt;
* [[4212]] DEPRECATED ERROR: DOS/Windows/Novell error 12&lt;br /&gt;
* [[4213]] DEPRECATED ERROR: DOS/Windows/Novell error 13&lt;br /&gt;
* [[4214]] DEPRECATED ERROR: DOS/Windows/Novell error 14&lt;br /&gt;
* [[4215]] Invalid drive reference&lt;br /&gt;
* [[4216]] Cannot remove directory&lt;br /&gt;
* [[4217]] DEPRECATED ERROR: DOS/Windows/Novell error 17&lt;br /&gt;
* [[4218]] DEPRECATED ERROR: DOS/Windows/Novell error 18&lt;br /&gt;
* [[4219]] I/O error on write protected floppy&lt;br /&gt;
* [[4220]] DEPRECATED ERROR: DOS/Windows/Novell error 20&lt;br /&gt;
* [[4221]] DEPRECATED ERROR: DOS/Windows/Novell error 21&lt;br /&gt;
* [[4222]] DEPRECATED ERROR: DOS/Windows/Novell error 22&lt;br /&gt;
* [[4223]] DEPRECATED ERROR: DOS/Windows/Novell error 23&lt;br /&gt;
* [[4224]] File is too large for locking mode&lt;br /&gt;
* [[4225]] DEPRECATED ERROR: DOS/Windows/Novell error 25&lt;br /&gt;
* [[4226]] DEPRECATED ERROR: DOS/Windows/Novell error 26&lt;br /&gt;
* [[4227]] DEPRECATED ERROR: DOS/Windows/Novell error 27&lt;br /&gt;
* [[4228]] DEPRECATED ERROR: DOS/Windows/Novell error 28&lt;br /&gt;
* [[4229]] DEPRECATED ERROR: DOS/Windows/Novell error 29&lt;br /&gt;
* [[4230]] DEPRECATED ERROR: DOS/Windows/Novell error 30&lt;br /&gt;
* [[4231]] DEPRECATED ERROR: DOS/Windows/Novell error 31&lt;br /&gt;
* [[4232]] DEPRECATED ERROR: DOS/Windows/Novell error 32&lt;br /&gt;
* [[4233]] DEPRECATED ERROR: DOS/Windows/Novell error 33&lt;br /&gt;
* [[4234]] DEPRECATED ERROR: DOS/Windows/Novell error 34&lt;br /&gt;
* [[4235]] DEPRECATED ERROR: DOS/Windows/Novell error 35&lt;br /&gt;
* [[4236]] DEPRECATED ERROR: DOS/Windows/Novell error 36&lt;br /&gt;
* [[4237]] DEPRECATED ERROR: DOS/Windows/Novell error 37&lt;br /&gt;
* [[4238]] DEPRECATED ERROR: DOS/Windows/Novell error 38&lt;br /&gt;
* [[4239]] Disk is full&lt;br /&gt;
* [[4240]] DEPRECATED ERROR: DOS/Windows/Novell error 40&lt;br /&gt;
* [[4241]] DEPRECATED ERROR: DOS/Windows/Novell error 41&lt;br /&gt;
* [[4242]] DEPRECATED ERROR: DOS/Windows/Novell error 42&lt;br /&gt;
* [[4243]] DEPRECATED ERROR: DOS/Windows/Novell error 43&lt;br /&gt;
* [[4244]] DEPRECATED ERROR: DOS/Windows/Novell error 44&lt;br /&gt;
* [[4245]] DEPRECATED ERROR: DOS/Windows/Novell error 45&lt;br /&gt;
* [[4246]] DEPRECATED ERROR: DOS/Windows/Novell error 46&lt;br /&gt;
* [[4247]] DEPRECATED ERROR: DOS/Windows/Novell error 47&lt;br /&gt;
* [[4248]] DEPRECATED ERROR: DOS/Windows/Novell error 48&lt;br /&gt;
* [[4249]] DEPRECATED ERROR: DOS/Windows/Novell error 49&lt;br /&gt;
* [[4250]] DEPRECATED ERROR: DOS/Windows/Novell error 50&lt;br /&gt;
* [[4251]] DEPRECATED ERROR: DOS/Windows/Novell error 51&lt;br /&gt;
* [[4252]] DEPRECATED ERROR: DOS/Windows/Novell error 52&lt;br /&gt;
* [[4253]] DEPRECATED ERROR: DOS/Windows/Novell error 53&lt;br /&gt;
* [[4254]] DEPRECATED ERROR: DOS/Windows/Novell error 54&lt;br /&gt;
* [[4255]] DEPRECATED ERROR: DOS/Windows/Novell error 55&lt;br /&gt;
* [[4256]] DEPRECATED ERROR: DOS/Windows/Novell error 56&lt;br /&gt;
* [[4257]] DEPRECATED ERROR: DOS/Windows/Novell error 57&lt;br /&gt;
* [[4258]] DEPRECATED ERROR: DOS/Windows/Novell error 58&lt;br /&gt;
* [[4259]] DEPRECATED ERROR: DOS/Windows/Novell error 59&lt;br /&gt;
* [[4260]] DEPRECATED ERROR: DOS/Windows/Novell error 60&lt;br /&gt;
* [[4261]] Printer queue full&lt;br /&gt;
* [[4262]] DEPRECATED ERROR: DOS/Windows/Novell error 62&lt;br /&gt;
* [[4263]] DEPRECATED ERROR: DOS/Windows/Novell error 63&lt;br /&gt;
* [[4264]] DEPRECATED ERROR: DOS/Windows/Novell error 64&lt;br /&gt;
* [[4265]] DEPRECATED ERROR: DOS/Windows/Novell error 65&lt;br /&gt;
* [[4266]] DEPRECATED ERROR: DOS/Windows/Novell error 66&lt;br /&gt;
* [[4267]] DEPRECATED ERROR: DOS/Windows/Novell error 67&lt;br /&gt;
* [[4268]] DEPRECATED ERROR: DOS/Windows/Novell error 68&lt;br /&gt;
* [[4269]] DEPRECATED ERROR: DOS/Windows/Novell error 69&lt;br /&gt;
* [[4270]] End of file&lt;br /&gt;
* [[4271]] Incomplete record&lt;br /&gt;
* [[4272]] Key not found&lt;br /&gt;
* [[4273]] Help keyword or topic not found&lt;br /&gt;
* [[4274]] DEPRECATED ERROR: DOS/Windows/Novell error 74&lt;br /&gt;
* [[4275]] DEPRECATED ERROR: DOS/Windows/Novell error 75&lt;br /&gt;
* [[4276]] Lock does not exist&lt;br /&gt;
* [[4277]] DEPRECATED ERROR: DOS/Windows/Novell error 77&lt;br /&gt;
* [[4278]] DEPRECATED ERROR: DOS/Windows/Novell error 78&lt;br /&gt;
* [[4279]] DEPRECATED ERROR: DOS/Windows/Novell error 79&lt;br /&gt;
* [[4280]]  DEPRECATED ERROR: DOS/Windows/Novell error 80&lt;br /&gt;
* [[4281]] DEPRECATED ERROR: DOS/Windows/Novell error 81&lt;br /&gt;
* [[4282]] Data does not match LINK=&lt;br /&gt;
* [[4283]] Updating previous/next link failed&lt;br /&gt;
* [[4284]] DEPRECATED ERROR: DOS/Windows/Novell error 84&lt;br /&gt;
* [[4285]] DEPRECATED ERROR: DOS/Windows/Novell error 85&lt;br /&gt;
* [[4286]] DEPRECATED ERROR: DOS/Windows/Novell error 86&lt;br /&gt;
* [[4287]] DEPRECATED ERROR: DOS/Windows/Novell error 87&lt;br /&gt;
* [[4288]] DEPRECATED ERROR: DOS/Windows/Novell error 88&lt;br /&gt;
* [[4289]] DEPRECATED ERROR: DOS/Windows/Novell error 89&lt;br /&gt;
* [[4290]] DEPRECATED ERROR: DOS/Windows/Novell error 90&lt;br /&gt;
* [[4291]] DEPRECATED ERROR: DOS/Windows/Novell error 91&lt;br /&gt;
* [[4292]] DEPRECATED ERROR: DOS/Windows/Novell error 92&lt;br /&gt;
* [[4293]] DEPRECATED ERROR: DOS/Windows/Novell error 93&lt;br /&gt;
* [[4294]] DEPRECATED ERROR: DOS/Windows/Novell error 94&lt;br /&gt;
* [[4295]] DEPRECATED ERROR: DOS/Windows/Novell error 95&lt;br /&gt;
* [[4296]] DEPRECATED ERROR: DOS/Windows/Novell error 96&lt;br /&gt;
* [[4297]] DEPRECATED ERROR: DOS/Windows/Novell error 97&lt;br /&gt;
* [[4298]] DEPRECATED ERROR: DOS/Windows/Novell error 98&lt;br /&gt;
* [[4299]] Cannot copy or rename file to itself&lt;br /&gt;
&lt;br /&gt;
* [[4300]] Shell call return value&lt;br /&gt;
* [[4301]] DEPRECATED ERROR: DOS/Windows/Novell error 101&lt;br /&gt;
* [[4302]] DEPRECATED ERROR: DOS/Windows/Novell error 102&lt;br /&gt;
* [[4303]] DEPRECATED ERROR: DOS/Windows/Novell error 103&lt;br /&gt;
* [[4304]] DEPRECATED ERROR: DOS/Windows/Novell error 104&lt;br /&gt;
* [[4305]] DEPRECATED ERROR: DOS/Windows/Novell error 105&lt;br /&gt;
* [[4306]] DEPRECATED ERROR: DOS/Windows/Novell error 106&lt;br /&gt;
* [[4307]] DEPRECATED ERROR: DOS/Windows/Novell error 107&lt;br /&gt;
* [[4308]] DEPRECATED ERROR: DOS/Windows/Novell error 108&lt;br /&gt;
* [[4309]] DEPRECATED ERROR: DOS/Windows/Novell error 109&lt;br /&gt;
* [[4310]] DEPRECATED ERROR: DOS/Windows/Novell error 110&lt;br /&gt;
* [[4311]] DEPRECATED ERROR: DOS/Windows/Novell error 111&lt;br /&gt;
* [[4312]] DEPRECATED ERROR: DOS/Windows/Novell error 112&lt;br /&gt;
* [[4313]] DEPRECATED ERROR: DOS/Windows/Novell error 113&lt;br /&gt;
* [[4314]] DEPRECATED ERROR: DOS/Windows/Novell error 114&lt;br /&gt;
* [[4315]] DEPRECATED ERROR: DOS/Windows/Novell error 115&lt;br /&gt;
* [[4316]] DEPRECATED ERROR: DOS/Windows/Novell error 116&lt;br /&gt;
* [[4317]] DEPRECATED ERROR: DOS/Windows/Novell error 117&lt;br /&gt;
* [[4318]] DEPRECATED ERROR: DOS/Windows/Novell error 118&lt;br /&gt;
* [[4319]] DEPRECATED ERROR: DOS/Windows/Novell error 119&lt;br /&gt;
* [[4320]] Unknown system error see SYSERR function&lt;br /&gt;
* [[4321]] DEPRECATED ERROR: DOS/Windows/Novell error 121&lt;br /&gt;
* [[4322]] DEPRECATED ERROR: DOS/Windows/Novell error 122&lt;br /&gt;
* [[4323]] DEPRECATED ERROR: DOS/Windows/Novell error 123&lt;br /&gt;
* [[4324]] DEPRECATED ERROR: DOS/Windows/Novell error 124&lt;br /&gt;
* [[4325]] DEPRECATED ERROR: DOS/Windows/Novell error 125&lt;br /&gt;
* [[4326]] DEPRECATED ERROR: DOS/Windows/Novell error 126&lt;br /&gt;
* [[4327]] DEPRECATED ERROR: DOS/Windows/Novell error 127&lt;br /&gt;
* [[4328]] DEPRECATED ERROR: DOS/Windows/Novell error 128&lt;br /&gt;
* [[4329]] DEPRECATED ERROR: DOS/Windows/Novell error 129&lt;br /&gt;
* [[4330]] DEPRECATED ERROR: DOS/Windows/Novell error 130&lt;br /&gt;
* [[4331]] DEPRECATED ERROR: DOS/Windows/Novell error 131&lt;br /&gt;
* [[4332]] DEPRECATED ERROR: DOS/Windows/Novell error 132&lt;br /&gt;
* [[4333]] DEPRECATED ERROR: DOS/Windows/Novell error 133&lt;br /&gt;
* [[4334]] DEPRECATED ERROR: DOS/Windows/Novell error 134&lt;br /&gt;
* [[4335]] DEPRECATED ERROR: DOS/Windows/Novell error 135&lt;br /&gt;
* [[4336]] DEPRECATED ERROR: DOS/Windows/Novell error 136&lt;br /&gt;
* [[4337]] DEPRECATED ERROR: DOS/Windows/Novell error 137&lt;br /&gt;
* [[4338]] DEPRECATED ERROR: DOS/Windows/Novell error 138&lt;br /&gt;
* [[4339]] DEPRECATED ERROR: DOS/Windows/Novell error 139&lt;br /&gt;
* [[4340]] Unknown curl error - use -e to return OS error&lt;br /&gt;
* [[4341]] DEPRECATED ERROR: DOS/Windows/Novell error 141&lt;br /&gt;
* [[4342]] DEPRECATED ERROR: DOS/Windows/Novell error 142&lt;br /&gt;
* [[4343]] DEPRECATED ERROR: DOS/Windows/Novell error 143&lt;br /&gt;
* [[4344]] DEPRECATED ERROR: DOS/Windows/Novell error 144&lt;br /&gt;
* [[4345]] DEPRECATED ERROR: DOS/Windows/Novell error 145&lt;br /&gt;
* [[4346]] DEPRECATED ERROR: DOS/Windows/Novell error 146&lt;br /&gt;
* [[4347]] DEPRECATED ERROR: DOS/Windows/Novell error 147&lt;br /&gt;
* [[4348]] DEPRECATED ERROR: DOS/Windows/Novell error 148&lt;br /&gt;
* [[4349]] DEPRECATED ERROR: DOS/Windows/Novell error 149&lt;br /&gt;
* [[4350]] DEPRECATED ERROR: DOS/Windows/Novell error 150&lt;br /&gt;
* [[4351]] DEPRECATED ERROR: DOS/Windows/Novell error 151&lt;br /&gt;
* [[4352]] DEPRECATED ERROR: DOS/Windows/Novell error 152&lt;br /&gt;
* [[4353]] DEPRECATED ERROR: DOS/Windows/Novell error 153&lt;br /&gt;
* [[4354]] DEPRECATED ERROR: DOS/Windows/Novell error 154&lt;br /&gt;
* [[4355]] DEPRECATED ERROR: DOS/Windows/Novell error 155&lt;br /&gt;
* [[4356]] DEPRECATED ERROR: DOS/Windows/Novell error 156&lt;br /&gt;
* [[4357]] DEPRECATED ERROR: DOS/Windows/Novell error 157&lt;br /&gt;
* [[4358]] DEPRECATED ERROR: DOS/Windows/Novell error 158&lt;br /&gt;
* [[4359]] DEPRECATED ERROR: DOS/Windows/Novell error 159&lt;br /&gt;
* [[4360]] DEPRECATED ERROR: DOS/Windows/Novell error 160&lt;br /&gt;
* [[4361]] DEPRECATED ERROR: DOS/Windows/Novell error 161&lt;br /&gt;
* [[4362]] DEPRECATED ERROR: DOS/Windows/Novell error 162&lt;br /&gt;
* [[4363]] DEPRECATED ERROR: DOS/Windows/Novell error 163&lt;br /&gt;
* [[4364]] DEPRECATED ERROR: DOS/Windows/Novell error 164&lt;br /&gt;
* [[4365]] DEPRECATED ERROR: DOS/Windows/Novell error 165&lt;br /&gt;
* [[4366]] DEPRECATED ERROR: DOS/Windows/Novell error 166&lt;br /&gt;
* [[4367]] DEPRECATED ERROR: DOS/Windows/Novell error 167&lt;br /&gt;
* [[4368]] DEPRECATED ERROR: DOS/Windows/Novell error 168&lt;br /&gt;
* [[4369]] DEPRECATED ERROR: DOS/Windows/Novell error 169&lt;br /&gt;
* [[4370]] DEPRECATED ERROR: DOS/Windows/Novell error 170&lt;br /&gt;
* [[4371]] DEPRECATED ERROR: DOS/Windows/Novell error 171&lt;br /&gt;
* [[4372]] DEPRECATED ERROR: DOS/Windows/Novell error 172&lt;br /&gt;
* [[4373]] DEPRECATED ERROR: DOS/Windows/Novell error 173&lt;br /&gt;
* [[4374]] DEPRECATED ERROR: DOS/Windows/Novell error 174&lt;br /&gt;
* [[4375]] DEPRECATED ERROR: DOS/Windows/Novell error 175&lt;br /&gt;
* [[4376]] DEPRECATED ERROR: DOS/Windows/Novell error 176&lt;br /&gt;
* [[4377]] DEPRECATED ERROR: DOS/Windows/Novell error 177&lt;br /&gt;
* [[4378]] DEPRECATED ERROR: DOS/Windows/Novell error 178&lt;br /&gt;
* [[4379]] DEPRECATED ERROR: DOS/Windows/Novell error 179&lt;br /&gt;
* [[4380]] DEPRECATED ERROR: DOS/Windows/Novell error 180&lt;br /&gt;
* [[4381]] DEPRECATED ERROR: DOS/Windows/Novell error 181&lt;br /&gt;
* [[4382]] DEPRECATED ERROR: DOS/Windows/Novell error 182&lt;br /&gt;
* [[4383]] DEPRECATED ERROR: DOS/Windows/Novell error 183&lt;br /&gt;
* [[4384]] DEPRECATED ERROR: DOS/Windows/Novell error 184&lt;br /&gt;
* [[4385]] DEPRECATED ERROR: DOS/Windows/Novell error 185&lt;br /&gt;
* [[4386]] DEPRECATED ERROR: DOS/Windows/Novell error 186&lt;br /&gt;
* [[4387]] DEPRECATED ERROR: DOS/Windows/Novell error 187&lt;br /&gt;
* [[4388]] DEPRECATED ERROR: DOS/Windows/Novell error 188&lt;br /&gt;
* [[4389]] DEPRECATED ERROR: DOS/Windows/Novell error 189&lt;br /&gt;
* [[4390]] DEPRECATED ERROR: DOS/Windows/Novell error 190&lt;br /&gt;
* [[4391]] DEPRECATED ERROR: DOS/Windows/Novell error 191&lt;br /&gt;
* [[4392]] DEPRECATED ERROR: DOS/Windows/Novell error 192&lt;br /&gt;
* [[4393]] DEPRECATED ERROR: DOS/Windows/Novell error 193&lt;br /&gt;
* [[4394]] DEPRECATED ERROR: DOS/Windows/Novell error 194&lt;br /&gt;
* [[4395]] DEPRECATED ERROR: DOS/Windows/Novell error 195&lt;br /&gt;
* [[4396]] DEPRECATED ERROR: DOS/Windows/Novell error 196&lt;br /&gt;
* [[4397]] DEPRECATED ERROR: DOS/Windows/Novell error 197&lt;br /&gt;
* [[4398]] DEPRECATED ERROR: DOS/Windows/Novell error 198&lt;br /&gt;
* [[4399]] File name is not a UNC path&lt;br /&gt;
&lt;br /&gt;
* [[4501]] OS function failure&lt;br /&gt;
* [[4513]] Bad data on OS function&lt;br /&gt;
* [[4514]] No memory on OS function&lt;br /&gt;
* [[4521]] Device not ready&lt;br /&gt;
* [[4522]] Bad system command&lt;br /&gt;
* [[4526]] Not a dos disk&lt;br /&gt;
* [[4591]] A shell call timed out&lt;br /&gt;
* [[4596]] Process signaled&lt;br /&gt;
* [[4597]] Process stopped&lt;br /&gt;
* [[4598]] Process was terminated in an unknown manner&lt;br /&gt;
* [[4614]] Invalid standard handle&lt;br /&gt;
* [[4616]] PDF library initialization failed&lt;br /&gt;
* [[4618]] An error that aborts further reconnect attempts has occurred&lt;br /&gt;
* [[4620]] Client server connection failure&lt;br /&gt;
* [[4890]] Temporary index creation failure&lt;br /&gt;
&lt;br /&gt;
* [[6201]] Spooling error while executing lp or lpr&lt;br /&gt;
* [[6213]] Unknown windows printing error&lt;br /&gt;
* [[6214]] Printing windlg find resource error&lt;br /&gt;
* [[6215]] Printing windlg initialization error&lt;br /&gt;
* [[6216]] Printing windlg load resource error&lt;br /&gt;
* [[6217]] Printing windlg load string failure&lt;br /&gt;
* [[6218]] Printing windlg lock resource failure&lt;br /&gt;
* [[6219]] Printing windlg no memory&lt;br /&gt;
* [[6220]] Printing windlg failed to lock memory&lt;br /&gt;
* [[6221]] Printing windlg no hisntance&lt;br /&gt;
* [[6222]] Printing windlg no hook&lt;br /&gt;
* [[6223]] Printing windlg no template&lt;br /&gt;
* [[6224]] Printing windlg struct size&lt;br /&gt;
* [[6225]] Printing windlg create IC failure&lt;br /&gt;
* [[6226]] Printing windlg default different&lt;br /&gt;
* [[6227]] Printing windlg drag and drop mismatch&lt;br /&gt;
* [[6228]] Printing windlg print dev mode failure&lt;br /&gt;
* [[6229]] Printing windlg error initializing printer&lt;br /&gt;
* [[6230]] Printing windlg error loading driver&lt;br /&gt;
* [[6231]] Printing windlg no default printer&lt;br /&gt;
* [[6232]] Printing windlg no devices&lt;br /&gt;
* [[6233]] Printing windlg parse failure&lt;br /&gt;
* [[6234]] Printing windlg printer not found&lt;br /&gt;
* [[6235]] Printing windlg return default failure&lt;br /&gt;
* [[6236]] Printing windlg setup failure&lt;br /&gt;
* [[6240]] Failed opening printer DC&lt;br /&gt;
* [[6242]] Invalid parametrized substitution format&lt;br /&gt;
* [[6243]] Parameter count does not match using parametrized substitutions&lt;br /&gt;
* [[6244]] Parametrized substitution result is too long&lt;br /&gt;
* [[6245]] Unsupported escape sequence for printing&lt;br /&gt;
* [[6246]] Passthrough printing error&lt;br /&gt;
* [[6247]] Invalid NWP color specification&lt;br /&gt;
* [[6248]] Invalid NWP picture specification or the image is not found&lt;br /&gt;
* [[6250]] Invalid PDF import specification&lt;br /&gt;
* [[6252]] Print PDF requires either READER or an output file name&lt;br /&gt;
* [[6254]] Creating a new PDF document failed&lt;br /&gt;
* [[6255]] Adding a page to a PDF document failed&lt;br /&gt;
* [[6256]] Ending a PDF document failed&lt;br /&gt;
* [[6257]] Adding an image to a PDF document failed&lt;br /&gt;
* [[6270]] Spooling error&lt;br /&gt;
* [[6272]] Bad initializer for PJL mode&lt;br /&gt;
* [[7600]] Invalid or missing key start position&lt;br /&gt;
* [[7601]] Invalid key length&lt;br /&gt;
* [[7602]] Bad key&lt;br /&gt;
* [[7603]] Duplicate keys found&lt;br /&gt;
* [[7604]] Missing parameters for INDEX&lt;br /&gt;
* [[7605]] Invalid index parameter&lt;br /&gt;
* [[7606]] INDEX records in does not match records out&lt;br /&gt;
* [[7607]] Not enough memory for INDEX&lt;br /&gt;
* [[7609]] Attempt to INDEX a file that is not an internal file&lt;br /&gt;
* [[7610]] Invalid INDEX file name&lt;br /&gt;
* [[7611]] INDEX file already exists&lt;br /&gt;
* [[7612]] Invalid INDEX work path&lt;br /&gt;
* [[7636]] INDEX interrupted by user&lt;br /&gt;
* [[7699]] Bad internal record size for INDEX&lt;br /&gt;
* [[7801]] Invalid sort keyword&lt;br /&gt;
* [[7804]] Syntax error in SORT - FILE specification&lt;br /&gt;
* [[7805]] Syntax error in SORT - RECORD specification&lt;br /&gt;
* [[7806]] Syntax error in SORT - ALTS specification&lt;br /&gt;
* [[7807]] Syntax error in SORT - MASK specification&lt;br /&gt;
* [[7809]] Syntax error in SORT - SUM specification&lt;br /&gt;
* [[7810]] Attempt to SORT a file that is not an internal file&lt;br /&gt;
* [[7811]] Not enough memory for SORT&lt;br /&gt;
* [[7812]] Invalid SORT output file type&lt;br /&gt;
* [[7821]] ALTS value is too large&lt;br /&gt;
* [[7823]] Missing MASK specification&lt;br /&gt;
* [[7825]] Too many RECORD statements&lt;br /&gt;
* [[7828]] SORT specifications out of order&lt;br /&gt;
* [[7829]] RECORD specification too long or too many RECORD specifications&lt;br /&gt;
* [[7830]] RECORD lower limit is greater than upper limit&lt;br /&gt;
* [[7831]] Output file record length is too short&lt;br /&gt;
* [[7832]] Output file not empty&lt;br /&gt;
* [[7853]] SORT control file not found&lt;br /&gt;
* [[8001]] DEPRECATED ERROR: number too long&lt;br /&gt;
* [[8002]] Window too small for input&lt;br /&gt;
* [[9000]] Out of memmory&lt;br /&gt;
* [[9001]] work stack is full&lt;br /&gt;
* [[9002]] RPN stack is full&lt;br /&gt;
* [[9003]] Flow stack is full&lt;br /&gt;
* [[9004]] FOR/NEXT stack is full&lt;br /&gt;
* [[9005]] RPN stack is empty&lt;br /&gt;
* [[9006]] Too many nested IF, FOR/NEXT or DO/LOOP structures&lt;br /&gt;
* [[9100]] DEPRECATED ERROR: compiler error&lt;br /&gt;
* [[9111]] Code byte count is incorrect&lt;br /&gt;
* [[9112]] Source byte count is incorrect&lt;br /&gt;
* [[9201]] Invalid access for opening a file&lt;br /&gt;
* [[9203]] Invalid create for opening a file&lt;br /&gt;
* [[9301]] Invalid number of RPN entries&lt;br /&gt;
* [[9302]] Function error&lt;br /&gt;
* [[9303]] Invalid function&lt;br /&gt;
* [[9304]] User defined function error&lt;br /&gt;
* [[9305]] User defined function error&lt;br /&gt;
* [[9306]] User defined function stacking error&lt;br /&gt;
* [[9307]] No editor defined or invalid ON error statement&lt;br /&gt;
* [[9308]] Utility open file channel is not open&lt;br /&gt;
* [[9309]] Corrupt .BR/.WB program file encountered&lt;br /&gt;
* [[9310]] Variable index outside of variable table&lt;br /&gt;
* [[9400]] DEPRECATED ERROR: output file corrupted&lt;br /&gt;
* [[9401]] BTREE verification failed&lt;br /&gt;
* [[9502]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9503]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9504]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9505]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9506]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9507]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9508]] DEVELOPMENT ERROR: Actual error code not assigned yet&lt;br /&gt;
* [[9985]] DEPRECATED ERROR: work file missing&lt;br /&gt;
* [[9987]] No source exists for the given file&lt;br /&gt;
* [[9988]] DEPRECATED ERROR: source line greater than 800 bytes&lt;br /&gt;
* [[9990]] This version was made without HTTP support&lt;br /&gt;
* [[9992]] DEF statement compiler error&lt;br /&gt;
* [[9994]] Line reference indicates library, but no libraries active&lt;br /&gt;
* [[9995]] DEPRECATED ERROR: RPN stack failure&lt;br /&gt;
* [[9996]] Library program not found or internal line not found&lt;br /&gt;
* [[9997]] Unbalanced parenthesis or flow stack error&lt;br /&gt;
* [[9998]] Corrupt DIM source&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Release 4.3]]&lt;br /&gt;
[[Category:Release Notes]]&lt;/div&gt;</summary>
		<author><name>Mikhail.zheleznov</name></author>
	</entry>
</feed>