<?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=Admin</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=Admin"/>
	<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Special:Contributions/Admin"/>
	<updated>2026-04-18T14:22:01Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Main_Page&amp;diff=6542</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Main_Page&amp;diff=6542"/>
		<updated>2013-07-31T14:28:13Z</updated>

		<summary type="html">&lt;p&gt;Admin: /* Other Business Rules! Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the &#039;&#039;&#039;{{SITENAME}}&#039;&#039;&#039;. This wiki is dedicated to the &#039;&#039;&#039;[[Business Rules!]]&#039;&#039;&#039; programming language (a.k.a. BR) and the software developers who use it. Currently containing [[Special:Statistics|{{NUMBEROFARTICLES}}]] articles,  this growing wiki is a great place to find information about the Business Rules! programming language. Our goal is to provide Business Rules! developers a convenient source of reference as well as an easy-to-use platform for documentation development. &lt;br /&gt;
&lt;br /&gt;
We encourage members of the [[BR Wiki:Community Portal|Business Rules! community]] to contribute their own knowledge to the Wiki. Everyone is encouraged to [[Special:Userlogin|register]] but editing is restricted to the [[BR Wiki:Administrators|editors group]]. &lt;br /&gt;
&lt;br /&gt;
If you come here often, you may be interested in just [[Special:Newpages|new pages]] or [[Special:Recentchanges|recent changes]]. If you&#039;d like to keep up with what&#039;s happening on the BR! Wiki you are welcome to [http://brwiki.ads.net/index.php?title=Special:Recentchanges&amp;amp;feed=rss subscribe to the recent changes RSS]. &lt;br /&gt;
&lt;br /&gt;
== For New Users ==&lt;br /&gt;
&lt;br /&gt;
*[http://meta.wikimedia.org/wiki/Help:Contents Help Using the Wiki]&lt;br /&gt;
*[[Special:Userlogin|Register]]&lt;br /&gt;
*[[BR Tutorial]]&lt;br /&gt;
*[http://brforum.brulescorp.com BR Forum]&lt;br /&gt;
&lt;br /&gt;
== Main Links ==&lt;br /&gt;
&lt;br /&gt;
*[[Business Rules!|Introduction]]&lt;br /&gt;
*[[Business Rules!|BR Reference]]&lt;br /&gt;
*[[Backward Compatibility]]&lt;br /&gt;
*[[:Category:Utilities Third Party|Utilities Third Party]]&lt;br /&gt;
*[http://brwiki.brulescorp.com Old Wiki]&lt;br /&gt;
*[http://www.ads.net/brules/download.html#BRUTILITIES Old BR Utilities]&lt;br /&gt;
*[[Export|Exporting the Wiki]]&lt;br /&gt;
&lt;br /&gt;
==ADS Official Links==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Application Development Systems&#039;&#039;&#039;, commonly called &#039;&#039;&#039;ADS&#039;&#039;&#039;, is the owner and distributor of the [[Business Rules!]].&lt;br /&gt;
&lt;br /&gt;
The links below are all hosted and maintained by ADS.&lt;br /&gt;
&lt;br /&gt;
*[http://ads.net/home.html ADS Home]&lt;br /&gt;
*[http://www.ads.net/brules/ Business Rules! Home]&lt;br /&gt;
*[http://www.ads.net/brules/advanced/index.html Advanced Capabilities]&lt;br /&gt;
*[http://www.ads.net/brules/dealers.html Dealers]&lt;br /&gt;
*[http://www.ads.net/brules/download.html Download]&lt;br /&gt;
*[ftp://ftp.ads.net/Dll_Distr/ ADS FTP Site]  (See also the BR Wiki&#039;s documentation of [[ADS FTP Site]].)&lt;br /&gt;
&lt;br /&gt;
==Business Rules! Related Links==&lt;br /&gt;
&lt;br /&gt;
*[http://www.sageax.com/br.html Sage Enterprises&#039; Business Rules! page]&lt;br /&gt;
*[http://br32.com/ BR32.com]&lt;br /&gt;
*[http://www.luisgomez.net/br/ Luis Gomez&#039;s BR page]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Main_Page&amp;diff=6541</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Main_Page&amp;diff=6541"/>
		<updated>2013-07-31T14:26:43Z</updated>

		<summary type="html">&lt;p&gt;Admin: /* Helpful Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the &#039;&#039;&#039;{{SITENAME}}&#039;&#039;&#039;. This wiki is dedicated to the &#039;&#039;&#039;[[Business Rules!]]&#039;&#039;&#039; programming language (a.k.a. BR) and the software developers who use it. Currently containing [[Special:Statistics|{{NUMBEROFARTICLES}}]] articles,  this growing wiki is a great place to find information about the Business Rules! programming language. Our goal is to provide Business Rules! developers a convenient source of reference as well as an easy-to-use platform for documentation development. &lt;br /&gt;
&lt;br /&gt;
We encourage members of the [[BR Wiki:Community Portal|Business Rules! community]] to contribute their own knowledge to the Wiki. Everyone is encouraged to [[Special:Userlogin|register]] but editing is restricted to the [[BR Wiki:Administrators|editors group]]. &lt;br /&gt;
&lt;br /&gt;
If you come here often, you may be interested in just [[Special:Newpages|new pages]] or [[Special:Recentchanges|recent changes]]. If you&#039;d like to keep up with what&#039;s happening on the BR! Wiki you are welcome to [http://brwiki.ads.net/index.php?title=Special:Recentchanges&amp;amp;feed=rss subscribe to the recent changes RSS]. &lt;br /&gt;
&lt;br /&gt;
== For New Users ==&lt;br /&gt;
&lt;br /&gt;
*[http://meta.wikimedia.org/wiki/Help:Contents Help Using the Wiki]&lt;br /&gt;
*[[Special:Userlogin|Register]]&lt;br /&gt;
*[[BR Tutorial]]&lt;br /&gt;
*[http://brforum.brulescorp.com BR Forum]&lt;br /&gt;
&lt;br /&gt;
== Main Links ==&lt;br /&gt;
&lt;br /&gt;
*[[Business Rules!|Introduction]]&lt;br /&gt;
*[[Business Rules!|BR Reference]]&lt;br /&gt;
*[[Backward Compatibility]]&lt;br /&gt;
*[[:Category:Utilities Third Party|Utilities Third Party]]&lt;br /&gt;
*[http://brwiki.brulescorp.com Old Wiki]&lt;br /&gt;
*[http://www.ads.net/brules/download.html#BRUTILITIES Old BR Utilities]&lt;br /&gt;
*[[Export|Exporting the Wiki]]&lt;br /&gt;
&lt;br /&gt;
==ADS Official Links==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Application Development Systems&#039;&#039;&#039;, commonly called &#039;&#039;&#039;ADS&#039;&#039;&#039;, is the owner and distributor of the [[Business Rules!]].&lt;br /&gt;
&lt;br /&gt;
The links below are all hosted and maintained by ADS.&lt;br /&gt;
&lt;br /&gt;
*[http://ads.net/home.html ADS Home]&lt;br /&gt;
*[http://www.ads.net/brules/ Business Rules! Home]&lt;br /&gt;
*[http://www.ads.net/brules/advanced/index.html Advanced Capabilities]&lt;br /&gt;
*[http://www.ads.net/brules/dealers.html Dealers]&lt;br /&gt;
*[http://www.ads.net/brules/download.html Download]&lt;br /&gt;
*[ftp://ftp.ads.net/Dll_Distr/ ADS FTP Site]  (See also the BR Wiki&#039;s documentation of [[ADS FTP Site]].)&lt;br /&gt;
&lt;br /&gt;
==Other Business Rules! Links==&lt;br /&gt;
&lt;br /&gt;
*[http://www.sageax.com/br.html Sage Enterprises&#039; Business Rules! page]&lt;br /&gt;
*[http://br32.com/ BR32.com]&lt;br /&gt;
*[http://www.luisgomez.net/br/ Luis Gomez&#039;s BR page]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Main_Page&amp;diff=6540</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Main_Page&amp;diff=6540"/>
		<updated>2013-07-31T14:24:12Z</updated>

		<summary type="html">&lt;p&gt;Admin: /* For New Users */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the &#039;&#039;&#039;{{SITENAME}}&#039;&#039;&#039;. This wiki is dedicated to the &#039;&#039;&#039;[[Business Rules!]]&#039;&#039;&#039; programming language (a.k.a. BR) and the software developers who use it. Currently containing [[Special:Statistics|{{NUMBEROFARTICLES}}]] articles,  this growing wiki is a great place to find information about the Business Rules! programming language. Our goal is to provide Business Rules! developers a convenient source of reference as well as an easy-to-use platform for documentation development. &lt;br /&gt;
&lt;br /&gt;
We encourage members of the [[BR Wiki:Community Portal|Business Rules! community]] to contribute their own knowledge to the Wiki. Everyone is encouraged to [[Special:Userlogin|register]] but editing is restricted to the [[BR Wiki:Administrators|editors group]]. &lt;br /&gt;
&lt;br /&gt;
If you come here often, you may be interested in just [[Special:Newpages|new pages]] or [[Special:Recentchanges|recent changes]]. If you&#039;d like to keep up with what&#039;s happening on the BR! Wiki you are welcome to [http://brwiki.ads.net/index.php?title=Special:Recentchanges&amp;amp;feed=rss subscribe to the recent changes RSS]. &lt;br /&gt;
&lt;br /&gt;
== For New Users ==&lt;br /&gt;
&lt;br /&gt;
*[http://meta.wikimedia.org/wiki/Help:Contents Help Using the Wiki]&lt;br /&gt;
*[[Special:Userlogin|Register]]&lt;br /&gt;
*[[BR Tutorial]]&lt;br /&gt;
*[http://brforum.brulescorp.com BR Forum]&lt;br /&gt;
&lt;br /&gt;
== Helpful Links ==&lt;br /&gt;
&lt;br /&gt;
*[[Business Rules!|BR Reference]]&lt;br /&gt;
*[http://brforum.brulescorp.com BR Forum]&lt;br /&gt;
*[http://brwiki.brulescorp.com Old Wiki]&lt;br /&gt;
*[http://www.ads.net/brules/download.html#BRUTILITIES Old BR Utilities]&lt;br /&gt;
*[[:Category:Utilities Third Party|Utilities Third Party]]&lt;br /&gt;
*[[Backward Compatibility]]&lt;br /&gt;
*[[Export|Exporting the Wiki]]&lt;br /&gt;
*[[BR Tutorial]]&lt;br /&gt;
&lt;br /&gt;
==ADS Official Links==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Application Development Systems&#039;&#039;&#039;, commonly called &#039;&#039;&#039;ADS&#039;&#039;&#039;, is the owner and distributor of the [[Business Rules!]].&lt;br /&gt;
&lt;br /&gt;
The links below are all hosted and maintained by ADS.&lt;br /&gt;
&lt;br /&gt;
*[http://ads.net/home.html ADS Home]&lt;br /&gt;
*[http://www.ads.net/brules/ Business Rules! Home]&lt;br /&gt;
*[http://www.ads.net/brules/advanced/index.html Advanced Capabilities]&lt;br /&gt;
*[http://www.ads.net/brules/dealers.html Dealers]&lt;br /&gt;
*[http://www.ads.net/brules/download.html Download]&lt;br /&gt;
*[ftp://ftp.ads.net/Dll_Distr/ ADS FTP Site]  (See also the BR Wiki&#039;s documentation of [[ADS FTP Site]].)&lt;br /&gt;
&lt;br /&gt;
==Other Business Rules! Links==&lt;br /&gt;
&lt;br /&gt;
*[http://www.sageax.com/br.html Sage Enterprises&#039; Business Rules! page]&lt;br /&gt;
*[http://br32.com/ BR32.com]&lt;br /&gt;
*[http://www.luisgomez.net/br/ Luis Gomez&#039;s BR page]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Business_Rules!&amp;diff=6539</id>
		<title>Business Rules!</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Business_Rules!&amp;diff=6539"/>
		<updated>2013-07-31T14:07:20Z</updated>

		<summary type="html">&lt;p&gt;Admin: minor edits re programming philosophy&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;====General Introduction====&lt;br /&gt;
&#039;&#039;&#039;Business Rules!&#039;&#039;&#039;, also known as &#039;&#039;&#039;BR&#039;&#039;&#039; is a derivative of ANSI Basic similar to that used on IBM mid-frame computers. It is a highly readable &#039;&#039;&#039;cross-platform&#039;&#039;&#039; [[programming language]] used by procedural programmers to build applications in a top-down building block structure. &lt;br /&gt;
&lt;br /&gt;
In the modern world there are three general types of programming languages:&lt;br /&gt;
* Procedural -  Where program control flow is the primary focus while the code creates, processes and destroys representations of external reality.&lt;br /&gt;
* Non-Procedural - Where various elements are defined with snippets of code attached to events which are triggered by either users or other programs.&lt;br /&gt;
* Object Oriented - Which is a blend of the preceding types with predefined rules for creating and deleting representations of external reality, and program defined methods of accessing them. This language structure was introduced to the programming world as C++, and has become the predominate programming language model. &lt;br /&gt;
&lt;br /&gt;
The advent of the World Wide Web introduced the widespread acceptance of the connectionless client/server model, with [[tunneled methods]] of achieving connection persistence. This technique was implemented by the Microsoft Dot Net programming languages. Another concept implemented by both Dot Net and Java was the use of a compiled pseudo-code executable which is made portable by providing execution engines for each platform. &lt;br /&gt;
&lt;br /&gt;
====RESTful Characteristics====&lt;br /&gt;
Representational State Transfer (REST) is a style of software architecture for distributed systems such as the World Wide Web and [[loosely coupled]] application frameworks. Key goals of REST include:&lt;br /&gt;
&lt;br /&gt;
* Scalability of component interactions&lt;br /&gt;
* Generality of interfaces&lt;br /&gt;
* Independent deployment of components&lt;br /&gt;
* Intermediary components to reduce latency, enforce security and encapsulate legacy systems&lt;br /&gt;
&lt;br /&gt;
The strength of many programming languages lies in their ability to express immense amounts of processing control specifications in relatively few statements. This is achieved in object oriented languages by the concepts of inheritance and overloading. While these concepts work well for creating and using tool sets, where all users learn the tools as an extension of the underlying language, a pervasive problem associated with them is that in an application framework it is necessary for users of objects to be aware of processing details of the objects they inherit from. Again, this works extremely well for tool sets, and not so well where 1) large sets of programs are shared among many programmers, 2) where programs are part of a networked set of applications, and 3) where a large set of programs must be modified by someone who is not entirely familiar with them. &lt;br /&gt;
&lt;br /&gt;
Truly RESTful systems insulate nodes from the requirement of knowing processing details within other nodes. &lt;br /&gt;
&lt;br /&gt;
====BR Characteristics====&lt;br /&gt;
Business Rules! is a procedural language that conforms to REST principles. Its unique set of rules for utilizing libraries to create program building blocks, along with its general readability, position it well for both beginning programmers and large scale projects. &lt;br /&gt;
&lt;br /&gt;
This language is being adopted by a growing number of young programmers due to it&#039;s ability to quickly develop procedural programs that include:&lt;br /&gt;
&lt;br /&gt;
* powerful string and array manipulation&lt;br /&gt;
* [[character position oriented window, field and report specification]]&lt;br /&gt;
* HTTP client emulation&lt;br /&gt;
* serial communications for industrial applications&lt;br /&gt;
* PDF printing with background forms&lt;br /&gt;
* both flat file processing with multiple indexes and traditional database support&lt;br /&gt;
* powerful built-in parsing functions for XML and CSV strings&lt;br /&gt;
&lt;br /&gt;
and have it run in a framework with:&lt;br /&gt;
* a [[client server architecture]]&lt;br /&gt;
* a portable pseudo-code executable format&lt;br /&gt;
* dynamic interactive debugging&lt;br /&gt;
* uniquely readable building block programming ( libraries )&lt;br /&gt;
* performance profiling&lt;br /&gt;
* an HTTP server add-on with JSON compilation and manipulation &lt;br /&gt;
&lt;br /&gt;
BR handles platform dependencies independently from code, so it is easy to maintain one set of programs for all supported platforms (Windows, Linux and MAC).&lt;br /&gt;
&lt;br /&gt;
The BR Programming Language is comprised of [[Environmental Settings]], [[Commands]], [[Variable|Variables]], [[Internal Functions|Functions]], [[Expression Logic]] and [[Program Statements]].  Programs are compiled into virtual code that is executed by a run-time executive. This supports a high degree of portability across platforms. The interactive nature of BR facilitates relatively easy debugging because you can change a program while it is running, as well as execute commands and statements from it&#039;s [[command console]].&lt;br /&gt;
&lt;br /&gt;
Business Rules! strong commitment to providing backward compatibility options ensures that any investment in BR programs will be protected nearly indefinitely.  While some of Business Rules! syntax may seem too simplistic to someone versed in more complex object oriented programming, the language&#039;s inability to hide code enhances readability. &lt;br /&gt;
&lt;br /&gt;
See also: [[BR Wiki:Community Portal]]&lt;br /&gt;
&lt;br /&gt;
== Getting Started ==&lt;br /&gt;
&lt;br /&gt;
*BR [[Setup]]&lt;br /&gt;
&lt;br /&gt;
*[[Getting Started]]&lt;br /&gt;
&lt;br /&gt;
== Categories  ==&lt;br /&gt;
&lt;br /&gt;
Most of this wiki is categorized. An individual article may belong to multiple categories. The [[Special:Uncategorizedcategories|Top Level Categories]] are a nice way to browse this wiki. In the table below are the most popular categories.&lt;br /&gt;
&lt;br /&gt;
*[[:Category:Commands|Commands]]&lt;br /&gt;
*[[:Category:Variable|Variables]]&lt;br /&gt;
*[[:Category:Arrays|Arrays]]&lt;br /&gt;
*[[:Category:Operations|Operations]]&lt;br /&gt;
*[[:Category:Internal Functions|Internal Functions]]&lt;br /&gt;
*[[:Category:Field Specifications|Field Specifications]]&lt;br /&gt;
*[[:Category:Definitions|Definitions]]&lt;br /&gt;
*[[:Category:Statements|Statements]]&lt;br /&gt;
*[[:Category:Control_Structures|Control Structures]]&lt;br /&gt;
*[[:Category:File_Operations|File Operations]]&lt;br /&gt;
*[[:Category:Sorting_and_Indexing|Sorting and Indexing]]&lt;br /&gt;
*[[:Category:GUI|Widgets / GUI]]&lt;br /&gt;
*[[:Category:Properties_Events_and_Methods|Properties, Events and Methods]]&lt;br /&gt;
*[[:Category:User_Defined_Functions_and_Libraries|User Defined Functions / Libraries]]&lt;br /&gt;
*[[:Category:Config|Configuration and Environmental Settings]]&lt;br /&gt;
*[[:Category:Printing|Printing]]&lt;br /&gt;
*[[:Category:HTTP|HTTP]]&lt;br /&gt;
*[[:Category:External_Editors|External Editors]]&lt;br /&gt;
*[[:Category:Terminology|Glossary / Terminology]]&lt;br /&gt;
*[[:Category:Error|Error Handling]]&lt;br /&gt;
*[[:Category:Error Codes|Error Codes]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Main_Page&amp;diff=3511</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Main_Page&amp;diff=3511"/>
		<updated>2013-06-26T23:47:14Z</updated>

		<summary type="html">&lt;p&gt;Admin: /* Helpful Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the &#039;&#039;&#039;{{SITENAME}}&#039;&#039;&#039;. This wiki is dedicated to the &#039;&#039;&#039;[[Business Rules!]]&#039;&#039;&#039; programming language (a.k.a. BR) and the software developers who use it. Currently containing [[Special:Statistics|{{NUMBEROFARTICLES}}]] articles,  this growing wiki is a great place to find information about the Business Rules! programming language. Our goal is to provide Business Rules! developers a convenient source of reference as well as an easy-to-use platform for documentation development. &lt;br /&gt;
&lt;br /&gt;
We encourage members of the [[BR Wiki:Community Portal|Business Rules! community]] to contribute their own knowledge to the Wiki. Everyone is encouraged to [[Special:Userlogin|register]] but editing is restricted to the [[BR Wiki:Administrators|editors group]]. &lt;br /&gt;
&lt;br /&gt;
If you come here often, you may be interested in just [[Special:Newpages|new pages]] or [[Special:Recentchanges|recent changes]]. If you&#039;d like to keep up with what&#039;s happening on the BR! Wiki you are welcome to [http://brwiki.ads.net/index.php?title=Special:Recentchanges&amp;amp;feed=rss subscribe to the recent changes RSS]. &lt;br /&gt;
&lt;br /&gt;
== For New Users ==&lt;br /&gt;
&lt;br /&gt;
*[http://meta.wikimedia.org/wiki/Help:Contents Help Using the Wiki]&lt;br /&gt;
*[[Special:Userlogin|Register]]&lt;br /&gt;
&lt;br /&gt;
== Helpful Links ==&lt;br /&gt;
&lt;br /&gt;
*[[Business Rules!|BR Reference]]&lt;br /&gt;
*[http://brforum.brulescorp.com BR Forum]&lt;br /&gt;
*[http://brwiki.brulescorp.com Old Wiki]&lt;br /&gt;
*[http://www.ads.net/brules/download.html#BRUTILITIES Old BR Utilities]&lt;br /&gt;
*[[:Category:Utilities Third Party|Utilities Third Party]]&lt;br /&gt;
*[[Backward Compatibility]]&lt;br /&gt;
*[[Export|Exporting the Wiki]]&lt;br /&gt;
*[[BR Tutorial]]&lt;br /&gt;
&lt;br /&gt;
==ADS Official Links==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Application Development Systems&#039;&#039;&#039;, commonly called &#039;&#039;&#039;ADS&#039;&#039;&#039;, is the owner and distributor of the [[Business Rules!]].&lt;br /&gt;
&lt;br /&gt;
The links below are all hosted and maintained by ADS.&lt;br /&gt;
&lt;br /&gt;
*[http://ads.net/home.html ADS Home]&lt;br /&gt;
*[http://www.ads.net/brules/ Business Rules! Home]&lt;br /&gt;
*[http://www.ads.net/brules/advanced/index.html Advanced Capabilities]&lt;br /&gt;
*[http://www.ads.net/brules/dealers.html Dealers]&lt;br /&gt;
*[http://www.ads.net/brules/download.html Download]&lt;br /&gt;
*[ftp://ftp.ads.net/Dll_Distr/ ADS FTP Site]  (See also the BR Wiki&#039;s documentation of [[ADS FTP Site]].)&lt;br /&gt;
&lt;br /&gt;
==Other Business Rules! Links==&lt;br /&gt;
&lt;br /&gt;
*[http://www.sageax.com/br.html Sage Enterprises&#039; Business Rules! page]&lt;br /&gt;
*[http://br32.com/ BR32.com]&lt;br /&gt;
*[http://www.luisgomez.net/br/ Luis Gomez&#039;s BR page]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Main_Page&amp;diff=3510</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Main_Page&amp;diff=3510"/>
		<updated>2013-06-26T23:46:55Z</updated>

		<summary type="html">&lt;p&gt;Admin: /* Helpful Links */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welcome to the &#039;&#039;&#039;{{SITENAME}}&#039;&#039;&#039;. This wiki is dedicated to the &#039;&#039;&#039;[[Business Rules!]]&#039;&#039;&#039; programming language (a.k.a. BR) and the software developers who use it. Currently containing [[Special:Statistics|{{NUMBEROFARTICLES}}]] articles,  this growing wiki is a great place to find information about the Business Rules! programming language. Our goal is to provide Business Rules! developers a convenient source of reference as well as an easy-to-use platform for documentation development. &lt;br /&gt;
&lt;br /&gt;
We encourage members of the [[BR Wiki:Community Portal|Business Rules! community]] to contribute their own knowledge to the Wiki. Everyone is encouraged to [[Special:Userlogin|register]] but editing is restricted to the [[BR Wiki:Administrators|editors group]]. &lt;br /&gt;
&lt;br /&gt;
If you come here often, you may be interested in just [[Special:Newpages|new pages]] or [[Special:Recentchanges|recent changes]]. If you&#039;d like to keep up with what&#039;s happening on the BR! Wiki you are welcome to [http://brwiki.ads.net/index.php?title=Special:Recentchanges&amp;amp;feed=rss subscribe to the recent changes RSS]. &lt;br /&gt;
&lt;br /&gt;
== For New Users ==&lt;br /&gt;
&lt;br /&gt;
*[http://meta.wikimedia.org/wiki/Help:Contents Help Using the Wiki]&lt;br /&gt;
*[[Special:Userlogin|Register]]&lt;br /&gt;
&lt;br /&gt;
== Helpful Links ==&lt;br /&gt;
&lt;br /&gt;
*[[Business Rules!|BR Reference]]&lt;br /&gt;
*[http://brforum.brulescorp.com BR Forum]&lt;br /&gt;
*[http://brwiki.brulescorp.com Old Wiki]&lt;br /&gt;
*[http://www.ads.net/brules/download.html#BRUTILITIES Old BR Utilities]&lt;br /&gt;
*[[:Category:Utilities Third Party]]&lt;br /&gt;
*[[Backward Compatibility]]&lt;br /&gt;
*[[Export|Exporting the Wiki]]&lt;br /&gt;
*[[BR Tutorial]]&lt;br /&gt;
&lt;br /&gt;
==ADS Official Links==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Application Development Systems&#039;&#039;&#039;, commonly called &#039;&#039;&#039;ADS&#039;&#039;&#039;, is the owner and distributor of the [[Business Rules!]].&lt;br /&gt;
&lt;br /&gt;
The links below are all hosted and maintained by ADS.&lt;br /&gt;
&lt;br /&gt;
*[http://ads.net/home.html ADS Home]&lt;br /&gt;
*[http://www.ads.net/brules/ Business Rules! Home]&lt;br /&gt;
*[http://www.ads.net/brules/advanced/index.html Advanced Capabilities]&lt;br /&gt;
*[http://www.ads.net/brules/dealers.html Dealers]&lt;br /&gt;
*[http://www.ads.net/brules/download.html Download]&lt;br /&gt;
*[ftp://ftp.ads.net/Dll_Distr/ ADS FTP Site]  (See also the BR Wiki&#039;s documentation of [[ADS FTP Site]].)&lt;br /&gt;
&lt;br /&gt;
==Other Business Rules! Links==&lt;br /&gt;
&lt;br /&gt;
*[http://www.sageax.com/br.html Sage Enterprises&#039; Business Rules! page]&lt;br /&gt;
*[http://br32.com/ BR32.com]&lt;br /&gt;
*[http://www.luisgomez.net/br/ Luis Gomez&#039;s BR page]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Third_party_utlity&amp;diff=3509</id>
		<title>Third party utlity</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Third_party_utlity&amp;diff=3509"/>
		<updated>2013-06-26T23:46:17Z</updated>

		<summary type="html">&lt;p&gt;Admin: Created page with &amp;quot;There are several third party utilities available for integration with your Business Rules! software system. Some of these have been written by companies that have never e...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;There are several third party utilities available for integration with your [[Business Rules!]] software system. Some of these have been written by companies that have never even heard of BR, but most of them have been written by the BR user community.&lt;br /&gt;
&lt;br /&gt;
*Third Party Utilities&lt;br /&gt;
**[[:Category:Install Builder|Install Builders]]&lt;br /&gt;
***[[Inno]]&lt;br /&gt;
***[[NSIS Setup]]&lt;br /&gt;
**BR Function Libraries&lt;br /&gt;
***[[fnSnap]]&lt;br /&gt;
***[[Fileio library]]&lt;br /&gt;
**Tools for extending the power of BR&lt;br /&gt;
***[[AutoIt]]&lt;br /&gt;
***[[BR Internet Bridge]]&lt;br /&gt;
***[[ScreenIO]]&lt;br /&gt;
***[[PhpIO]]&lt;br /&gt;
**Tools for making BR programming easier&lt;br /&gt;
***[[FreeEdit Linkage]]&lt;br /&gt;
***[[Notepad++]]&lt;br /&gt;
***[[MyEdit (BR Edition)]]&lt;br /&gt;
***[[BR2BRS|WB2BRS and BR2BRS]] &lt;br /&gt;
***[[BRS2BR|BRS2WB and BRS2WB]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Category:Utilities_Third_Party&amp;diff=3508</id>
		<title>Category:Utilities Third Party</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Category:Utilities_Third_Party&amp;diff=3508"/>
		<updated>2013-06-26T23:45:44Z</updated>

		<summary type="html">&lt;p&gt;Admin: Created page with &amp;quot;{{:Third party utlity}}  Category:Utilities&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{:Third party utlity}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Utilities]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Category:3rd_Party_Utilities&amp;diff=3507</id>
		<title>Category:3rd Party Utilities</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Category:3rd_Party_Utilities&amp;diff=3507"/>
		<updated>2013-06-26T23:44:09Z</updated>

		<summary type="html">&lt;p&gt;Admin: Created page with &amp;quot;{{:Third party utlity}}  Category:Utilities&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{:Third party utlity}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Utilities]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=OPTION_33_mismatch_using_wbserver.dat&amp;diff=3505</id>
		<title>OPTION 33 mismatch using wbserver.dat</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=OPTION_33_mismatch_using_wbserver.dat&amp;diff=3505"/>
		<updated>2013-06-19T03:17:25Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Message box with a caption of &#039;&#039;&#039;Error&#039;&#039;&#039; stating &#039;&#039;&#039;[[OPTION]] 33 mismatch using [[wbserver.dat]]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Category:Error]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=536870914&amp;diff=3503</id>
		<title>536870914</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=536870914&amp;diff=3503"/>
		<updated>2013-06-19T03:17:25Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Problem===&lt;br /&gt;
Message box with a caption of &#039;&#039;&#039;Error&#039;&#039;&#039; and text reading &#039;&#039;&#039;Client-Server error 536870914, sending data.&#039;&#039;&#039;&lt;br /&gt;
===Solution===&lt;br /&gt;
Probably due to a massive over use of variables.&lt;br /&gt;
&lt;br /&gt;
One Customer experienced this during an index.   The issue ended up being hardware related, bad memory card on server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Client Server]]&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Couldn%27t_%27lock_in_progress%27&amp;diff=3501</id>
		<title>Couldn&#039;t &#039;lock in progress&#039;</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Couldn%27t_%27lock_in_progress%27&amp;diff=3501"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Couldn&#039;t lock in progress&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
This is a problem accessing the [[WBServer.dat]].  This lock is retried several times as other locks are.  It is possible that there are a lot of people starting [[BR!]] at the same time or that something is running slowly and holding its lock longer that normal.&lt;br /&gt;
&lt;br /&gt;
To recover from this error you can delete the WBServer.dat file and let BR.exe rebuild it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
*[[in progress]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[category:Error]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=The_requested_Workstation_ID_(WSID)_is_already_in_use_by_(UserName)&amp;diff=3499</id>
		<title>The requested Workstation ID (WSID) is already in use by (UserName)</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=The_requested_Workstation_ID_(WSID)_is_already_in_use_by_(UserName)&amp;diff=3499"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;On startup you receive a [[messagebox]] with a title of &#039;&#039;&#039;Error&#039;&#039;&#039; stating &#039;&#039;&#039;The requested Workstation ID (WSID) is already in use by (UserName)&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
This is probably due to the fact that (UserName) is logged into BR! with the same [[WSID]].&lt;br /&gt;
&lt;br /&gt;
If not, if may be due to a corrupt [[WBServer.dat]] file.&lt;br /&gt;
&lt;br /&gt;
There are many ways to address this issue.&lt;br /&gt;
&lt;br /&gt;
#Make [[WSID]] dynamic or add a +1 or +100 to the end of your WSID statement in your [[BRConfig.sys]]&lt;br /&gt;
#Use a different WSID&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Could_not_read_license_file.&amp;diff=3497</id>
		<title>Could not read license file.</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Could_not_read_license_file.&amp;diff=3497"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When attempting to use [[ODBC]] you might receive an error message box containing the text &#039;&#039;&#039;Could not read license file.&#039;&#039;&#039; with a caption of &#039;&#039;&#039;Business Rules!&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[category:Error]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Couldn%27t_open_wbserver&amp;diff=3495</id>
		<title>Couldn&#039;t open wbserver</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Couldn%27t_open_wbserver&amp;diff=3495"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Received a messagebox with a title of &#039;&#039;&#039;Error&#039;&#039;&#039; stating &#039;&#039;&#039;Couldn&#039;t open wbserver at BR Path=(path here). OS Path=(path here) Please check if it exists and current user has write permission.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
See also:&lt;br /&gt;
*[[WBServer.dat]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
[[Category:Client Server]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Couldn%27t_find_BRLISTENER.exe_in_the_specified_(or_SYSTEM)_directory&amp;diff=3493</id>
		<title>Couldn&#039;t find BRLISTENER.exe in the specified (or SYSTEM) directory</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Couldn%27t_find_BRLISTENER.exe_in_the_specified_(or_SYSTEM)_directory&amp;diff=3493"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Problem===&lt;br /&gt;
When attempting to launch [[install.exe]] you receive a [[messagebox]] with a title of [[BR Service Opening]] stating &#039;&#039;&#039;Couldn&#039;t find BRLISTENER.exe in the specified (or SYSTEM) directory&#039;&#039;&#039;.&lt;br /&gt;
===Solution===&lt;br /&gt;
Place [[BRlistener.exe]] in your [[C:\Windows\System32]] folder.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Client Server]]&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=10054&amp;diff=3491</id>
		<title>10054</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=10054&amp;diff=3491"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Client Server]] connection is broken.&lt;br /&gt;
&lt;br /&gt;
==Problem==&lt;br /&gt;
Receive a [[messagebox]] with a title of &#039;&#039;&#039;Error&#039;&#039;&#039; and a body stating &#039;&#039;&#039;Client-Server error 10054 receiving data.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Resolution==&lt;br /&gt;
Check the BRConfig.log (You must turn logging on).&lt;br /&gt;
Review the &amp;quot;Launch Line&amp;quot; (Something like this).&lt;br /&gt;
   Security process has started with command c:\...\BRServer.exe -c:\...\WBConfig.sys, startdir c:\...\, logfile c:\...\brconfig.log, loglevel 10, stderr file NULL, socket handle 120, anonymous NULL&lt;br /&gt;
   There will most likely be another line after it explaining the reason for the problem.&lt;br /&gt;
&lt;br /&gt;
*Error 10038 is Socket operation on nonsocket   -- This means the server was unable to connect to the workstation.&lt;br /&gt;
**Remember that while Port 8555 is typically used to initiate the inbound connection to BRListener, Ports 1024-65535 will be used to connect by to BRClient.&lt;br /&gt;
&lt;br /&gt;
*Most Windows Sockets 2 functions do not return the specific cause of an error when the function returns. For information, see the Handling Winsock Errors topic.&lt;br /&gt;
**http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668%28v=vs.85%29.aspx&lt;br /&gt;
&lt;br /&gt;
*Perhaps this is caused by a bad path in [[BRListener.conf]]&lt;br /&gt;
&lt;br /&gt;
*Mapped Network drives WILL NOT work as the BRServer session does not have mappings.&lt;br /&gt;
&lt;br /&gt;
*UNC names will work properly, but significantly affect performance.&lt;br /&gt;
&lt;br /&gt;
==Troubleshooting Tips==&lt;br /&gt;
&lt;br /&gt;
Host:  Make sure the server name is correct, in particular, you may have moved to a new server or IP address&lt;br /&gt;
&lt;br /&gt;
Label: This is case sensitive, and remember &amp;quot;Spaces&amp;quot; and perhaps other special characters require &amp;quot;&amp;quot; (Quotes)&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
[[Category:Client Server]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=10013&amp;diff=3489</id>
		<title>10013</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=10013&amp;diff=3489"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;quot;accept failed errno &#039;&#039;&#039;10013&#039;&#039;&#039;&amp;quot; reported in the [[client server]] log file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
[[Category:Client Server]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=BR_StartService_failed&amp;diff=3487</id>
		<title>BR StartService failed</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=BR_StartService_failed&amp;diff=3487"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A messagebox with a title of &#039;&#039;&#039;BR StartService failed&#039;&#039;&#039; and a message stating &#039;&#039;&#039;The service did not respond to the start or control request in a timely fashion.&#039;&#039;&#039; is displayed whey you launch [[install.exe]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
[[Category:Client Server]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=BRServer_cannot_be_started_directly.&amp;diff=3485</id>
		<title>BRServer cannot be started directly.</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=BRServer_cannot_be_started_directly.&amp;diff=3485"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Receive a messagebox with a caption of &#039;&#039;&#039;BusinessRules!&#039;&#039;&#039; and a message which states &#039;&#039;&#039;BRServer cannot be started directly. To run BR in client-server mode, install and start BRListener.exe&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
You need to run [[Install.exe]] (server side) to start the service, which will use BRListerner.exe.  BRListerner.exe should be located in the [[C:\Windows]] folder.&lt;br /&gt;
&lt;br /&gt;
See also:&lt;br /&gt;
*[[BRListener.exe]]&lt;br /&gt;
*[[Client Server]]&lt;br /&gt;
*[[BRServer.exe]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Client Server]]&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Socket_error&amp;diff=3483</id>
		<title>Socket error</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Socket_error&amp;diff=3483"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Problem==&lt;br /&gt;
When attempting to launch a [[Client Server]] version of [[Business Rules!]] you may receive a [[messagebox]] stating &#039;&#039;&#039;Connection failed&#039;&#039;&#039; with a caption which reads &#039;&#039;&#039;Socket error&#039;&#039;&#039;.  This is probably due to a bad configuration or lack of connectivity.&lt;br /&gt;
&lt;br /&gt;
==Solution==&lt;br /&gt;
Probably the Server side isn&#039;t started.  Go to the server and properly launch [[install.exe]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
[[Category:Client Server]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Network_error_processing_authentication&amp;diff=3481</id>
		<title>Network error processing authentication</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Network_error_processing_authentication&amp;diff=3481"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Receive a messagebox with a title of &#039;&#039;&#039;Error&#039;&#039;&#039; stating &#039;&#039;&#039;Network error processing authentication&#039;&#039;&#039; when trying to connect in [[Client Server]] [[BR!]]?&lt;br /&gt;
&lt;br /&gt;
Check the error logs and see if it is logging why.&lt;br /&gt;
&lt;br /&gt;
This may be due to an improperly configured [[BRListener.conf]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
[[Category:Client Server]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=ODBC_registration_problem&amp;diff=3479</id>
		<title>ODBC registration problem</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=ODBC_registration_problem&amp;diff=3479"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When attempting to use [[ODBC]] you receive a message box stating &amp;quot;ODBC registration problem&amp;quot; and &amp;quot;There was a problem registering this computer to use ODBC&amp;quot; with an OK button.&lt;br /&gt;
&lt;br /&gt;
This is generally due to a lack of ODBC licenses.  Contact [[BRC]] to upgrade your [[brserial.dat]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Executable_version&amp;diff=3477</id>
		<title>Executable version</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Executable_version&amp;diff=3477"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
Upon launch of [[Business Rules!]] you may receive a [[messagebox]] stating &#039;&#039;&#039;executable version ### does not match license version ###&#039;&#039;&#039; where ### are version numbers omitting periods.&lt;br /&gt;
&lt;br /&gt;
i.e.  &amp;quot;executable version 420 does not match license version 490&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[[brserial.dat]] needs to be more current&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Error]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Couldn%27t_get_lock_offset&amp;diff=3475</id>
		<title>Couldn&#039;t get lock offset</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Couldn%27t_get_lock_offset&amp;diff=3475"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When launching [[Business Rules!]] a &#039;&#039;&#039;Couldn&#039;t get lock offset.&#039;&#039;&#039; messagebox with a caption of &#039;&#039;&#039;Error&#039;&#039;&#039; is displayed.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
A solution is to exit all copies of [[Business Rules!]] on the workstation and then re-enter.&lt;br /&gt;
&lt;br /&gt;
This is probably due to an issue related to [[wbserver.dat]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[category:Error]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Wrong_version_of_wbserver.dat&amp;diff=3473</id>
		<title>Wrong version of wbserver.dat</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Wrong_version_of_wbserver.dat&amp;diff=3473"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When launching [[Business Rules!]] a &amp;quot;Wrong version of wbserver.dat&amp;quot; messagebox with a caption of &amp;quot;Error&amp;quot; is displayed.&lt;br /&gt;
&lt;br /&gt;
See also [[WBServer.dat]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Debugging_Errors&amp;diff=3471</id>
		<title>Debugging Errors</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Debugging_Errors&amp;diff=3471"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Debugging Errors&#039;&#039;&#039; we&#039;re released with [[4.18a]]&lt;br /&gt;
&lt;br /&gt;
Initially they only contained:&lt;br /&gt;
*[[0420]]&lt;br /&gt;
*[[0422]]&lt;br /&gt;
*[[0424]]&lt;br /&gt;
*[[0426]]&lt;br /&gt;
*[[0428]]&lt;br /&gt;
*[[0430]]&lt;br /&gt;
*[[0432]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
[[Category:Debug]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Category:Error_Conditions&amp;diff=3469</id>
		<title>Category:Error Conditions</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Category:Error_Conditions&amp;diff=3469"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Error Conditions are listed below.&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Assertion_Failed&amp;diff=3467</id>
		<title>Assertion Failed</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Assertion_Failed&amp;diff=3467"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Error&lt;br /&gt;
|Assertion Failed&lt;br /&gt;
|Assertion Failed&lt;br /&gt;
|&#039;&#039;&#039;Assertion failures&#039;&#039;&#039; and &#039;&#039;&#039;GPF&#039;&#039;&#039;s are usually caused by a corrupt [[br.exe]] or insufficient rights to something (often C:\windows\br.ini)&lt;br /&gt;
# BR does NOT have FULL permissions, to create the necessary files. &lt;br /&gt;
#*[[BRServer.dat]]&lt;br /&gt;
#*br.ini &lt;br /&gt;
|#The [[BRServer.dat]] is created in the location that is pointed to in the [[BRConfig.sys]], the [[BR.ini]] is created in the windows/system32 directory.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
BR.ini used to only get created when you did a save font size position, if you don&#039;t do that it never gets created. BRServer.dat gets created every time you load [[BR.EXE|BR!]]. In some versions of wb the previous [[WBServer.dat]] did not get deleted, and the new file never got made, and you would get the error too manyWBServer.dat found&lt;br /&gt;
&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Error Message:   Assertion Failed: t.sessionID, file wbs\Startup.c     &lt;br /&gt;
&lt;br /&gt;
When attempting to run WB from a workstation on a network where the user had all the necessary network rights to the network WB directories but did not have rights to the WinNT directory on the local workstation which is where the   WB.ini   file resides.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
[[Category:BR Manual Chapter 20]]&lt;br /&gt;
[[Category:Needs Help]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Category:Error_Codes&amp;diff=3465</id>
		<title>Category:Error Codes</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Category:Error_Codes&amp;diff=3465"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{:Error Codes}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Error]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Operating_System_Error&amp;diff=3463</id>
		<title>Operating System Error</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Operating_System_Error&amp;diff=3463"/>
		<updated>2013-06-19T03:17:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Operating System Errors&#039;&#039;&#039; may vary from OS to OS.  In older versions of Business Rules! errors in the 4200 series were all Operating System Errors.  The error number was calculated internally by BR by adding 4200 to the OS Error Number. Sometimes the resulting error code exceeded 4299 which conflicted with Unix / Linux error codes. Therefore in 4.16 this method was been replaced by generating BR errors [[4300]] and [[4320]], in combination with [[SysErr$]] and [[SysErr]].&lt;br /&gt;
&lt;br /&gt;
But most importantly, &#039;&#039;&#039;check the value of the variables SysErr and SysErr$ for a description of the error&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
For more information about Microsoft DOS and Windows OS Error Numbers see:  &lt;br /&gt;
&lt;br /&gt;
*[http://msdn.microsoft.com/en-us/library/ms681381(VS.85).aspx MSDN - System Error Codes]&lt;br /&gt;
*[http://support.tabs3.com/main/R10307.htm another nice OS Error Chart]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Operating System Error &lt;br /&gt;
72 - Print or disk redirection is paused. &lt;br /&gt;
267 - The directory name is invalid.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Error]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=BrMyAdmin&amp;diff=3461</id>
		<title>BrMyAdmin</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=BrMyAdmin&amp;diff=3461"/>
		<updated>2013-06-19T03:08:26Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;BrMyAdmin&#039;&#039;&#039; documentation coming soon!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Utilities Third Party]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=AuditBR&amp;diff=3459</id>
		<title>AuditBR</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=AuditBR&amp;diff=3459"/>
		<updated>2013-06-19T03:08:26Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Audit BR&#039;&#039;&#039; is a powerful new [[library]] from [[Sage AX]], created as a part of Sage AX&#039;s continuous mission to empower the BR developer with the latest in modern programming tools and techniques.&lt;br /&gt;
&lt;br /&gt;
Audit BR is a library that can be used to accomplish two simple functions, opening a powerful door for debugging your BR programs.&lt;br /&gt;
&lt;br /&gt;
Audit BR builds upon FileIO, enabling this powerful technology to work with your existing BR software right out of the box.&lt;br /&gt;
&lt;br /&gt;
More information about Audit BR is available at http://www.sageax.com/index.php?option=com_content&amp;amp;view=article&amp;amp;id=67 .&lt;br /&gt;
&lt;br /&gt;
= Description of Functions =&lt;br /&gt;
&lt;br /&gt;
== fnBeginAudit ==&lt;br /&gt;
&lt;br /&gt;
  fnBeginAudit(BackupFolder$)&lt;br /&gt;
  &lt;br /&gt;
  BackupFolder$ - the name of a folder to backup the Audit Information to. If it does not exist, it is created.&lt;br /&gt;
&lt;br /&gt;
The fnBeginAudit function makes a backup of your BR data files, essentially creating a restore point that can be compared at any time to your current data files, generating a report indicating clearly everything that has changed in the data files. To use it, simply call fnBeginAudit and give it the name of a folder to back the data up to. This folder should be a new folder, and it should not be used for any other purpose then for your BR datafile Audits.&lt;br /&gt;
&lt;br /&gt;
== fnCompare ==&lt;br /&gt;
&lt;br /&gt;
  fnCompare(BackupFolder$;Logfile$,Printer,DontClose)&lt;br /&gt;
  &lt;br /&gt;
  BackupFolder$ - the name of a folder containing a backup of your datafiles. Use fnBeginAudit to create and to update this folder.&lt;br /&gt;
  Logfile$ - The name of a logfile to report any changes to. The logfile is built on each time, so its a good idea to keep a logfile. If you run the audit routine regularly then you can use the logfile to determine not only what data has changed, but exactly when the change occured. If this field is blank or is not given, then the logfile is not created.&lt;br /&gt;
  Printer - this is a boolean flag indicating weather a report should be generated and sent to print preview or not. This report is color coded to make it easier to identify which elements of the data file have changed. When the program is being used and checked by a user or programmer, the printout is the easiest way to quickly make sense of the differences found in your data files.&lt;br /&gt;
  DontClose - use this optional boolean flag to force the fnCompare function to leave file #255 (the printer) open. Use this parameter if you want to keep from displaying the report in order to print more information on it before closing it yourself manually to generate the print job later.&lt;br /&gt;
&lt;br /&gt;
= Typical Usage =&lt;br /&gt;
&lt;br /&gt;
To use this library, you may run audit.br directly, or simply call these functions from your existing code. You can script the call to happen automatically, or you can place it on the user interface.&lt;br /&gt;
&lt;br /&gt;
== Example Usage 1 - User/Programmer Manual Trigger ==&lt;br /&gt;
&lt;br /&gt;
In one of my programs, I simply added an option on the menu to run an &amp;quot;Audit Report&amp;quot;. This menu option first calls fnCompare, then it calls fnBeginAudit right afterwords to create a restore point for the next comparison. I can run the menu option any time to see what has changed sinse the last time it was run.&lt;br /&gt;
&lt;br /&gt;
Any time I need to test a program change that modifies one or more data files in my system, I run the Audit Routine, then I run my new code, then I run the Audit Routine again. The Audit routine quickly generates a list of exactly which elements in the data file have changed and I&#039;m able to debug and double check my code in a fraction of the time it took to do it before. And more effecient debugging means fewer mistakes.&lt;br /&gt;
&lt;br /&gt;
== Example Usage 2 - Automatic Trigger (Interval) ==&lt;br /&gt;
&lt;br /&gt;
You might also want to make the Audit routine run automatically on a regular interval by a background process to build a running logfile showing all changes made to your system and the time that those changes were made.&lt;br /&gt;
&lt;br /&gt;
You can use Windows Task Scheduler to trigger the running of a program on a preset time interval.&lt;br /&gt;
&lt;br /&gt;
== Example Usage 3 - Automatic Trigger (Event Driven) ==&lt;br /&gt;
&lt;br /&gt;
It may be necessary to monitor what changes are made by each employee in the system. If you don&#039;t have a lot of employees using the system at the same time, one easy way to implement such a change may be to run the Audit routine each time a program is exited. Just prior to running the report, print a line to the logfile yourself saying what program just ran and who ran it. This would enable to you monitor the logfile to see exactly which user is responsible for a given change made to your system.&lt;br /&gt;
&lt;br /&gt;
= Notes =&lt;br /&gt;
&lt;br /&gt;
== Requires BR 4.1 or Above ==&lt;br /&gt;
&lt;br /&gt;
Because the Audit Report makes extensive use of NWP features, Audit BR requires BR 4.1 or above to run. Please note that your programs don&#039;t have to use BR 4.1. You can always just fire up a copy of BR 4.1 in order to run Audit and continue to use an earlier version of BR for the rest of your programs if you desire.&lt;br /&gt;
&lt;br /&gt;
== Workstack Requirements ==&lt;br /&gt;
&lt;br /&gt;
Audit BR requires FileIO, and FileIO requires a high Workstack value. If you recieve error 9001, try increasing the Workstack value specified in your brconfig.sys file. You can check your current workstack value at any time by using Status Stacks. The maximum value for Workstack under BR 4.1 and lower is 65535.&lt;br /&gt;
&lt;br /&gt;
== Files using Linux Style (&amp;quot;/&amp;quot;) Paths ==&lt;br /&gt;
&lt;br /&gt;
Audit BR is not compatable with using the &amp;quot;/&amp;quot; in your file layouts to describe the path for your data files. If you specify the filename for your data files (the first line of the file layout) using &amp;quot;/&amp;quot; linux style notation, please update your layouts and specify the path and filename for your data files using the &amp;quot;\&amp;quot; style Windows notation.&lt;br /&gt;
&lt;br /&gt;
[[Category:Utilities_Third_Party]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Color.exe&amp;diff=3457</id>
		<title>Color.exe</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Color.exe&amp;diff=3457"/>
		<updated>2013-06-19T03:08:26Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;Color.exe&#039;&#039;&#039; program came from [[Western Canadian Software]] at the Fall 2007 [[BRGroup Conference]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Utilities Third Party]]&lt;br /&gt;
[[Category:Files]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Programming_in_Jungles&amp;diff=3455</id>
		<title>Programming in Jungles</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Programming_in_Jungles&amp;diff=3455"/>
		<updated>2013-06-19T03:08:26Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Sometimes we&#039;re blazing a trail through unexplored territories we may write some [[Business Rules!]] programs along the way. Well out there in the jungle there is no internet. So if we want something from the web, we&#039;d better pack it to go first.  The easiest way to take this wiki with you is to make your own wiki on a stick (a.k.a. Thumb drive or USB drive) and export data from this wiki to it.  It&#039;s much simpler it sounds, thanks to some innovative work from [http://www.chsoftware.net/en/useware/mowes/mowes.htm CHSoftware].&lt;br /&gt;
&lt;br /&gt;
==DIY==&lt;br /&gt;
Want to create a personal web host on a stick?  Here&#039;s [[:Category:How To|how to]] do it:&lt;br /&gt;
&lt;br /&gt;
#Install a [http://www.mediawiki.org/wiki/Manual:Wiki_on_a_stick Wiki on a Stick] to your thumb drive.&lt;br /&gt;
:*The required packages (for our ends) are:&lt;br /&gt;
::#MediaWiki&lt;br /&gt;
::#PHP5&lt;br /&gt;
::#Apache Server&lt;br /&gt;
::#MySQL&lt;br /&gt;
:*Test and verify that you can access your &#039;&#039;wiki on a stick&#039;&#039;&lt;br /&gt;
#[[Special:Export|Export]] the desired [[Special:Uncategorizedcategories|Top level categories]] or [[Special:categories|any category]] or [[Special:Allpages|any single pages]] that you want from this wiki.  [[:Category:Templates|Templates]] are critical.&lt;br /&gt;
:*(Improvement in this step is planned, special categories will be made for the convenience of exporting)&lt;br /&gt;
:*Export sizes are limited, so you can&#039;t export EVERYTHING at once, but you can get quite a lot.&lt;br /&gt;
#Login to your new wiki with the user name &#039;&#039;Admin&#039;&#039; and the password &#039;&#039;password&#039;&#039;.&lt;br /&gt;
#Go to &#039;&#039;&#039;special pages&#039;&#039;&#039; and then &#039;&#039;&#039;Import&#039;&#039;&#039; (generally towards the end of the page).&lt;br /&gt;
#Choose the file that you previously exported (in step 2)&lt;br /&gt;
&lt;br /&gt;
That&#039;s it.  Now when you are ready to launch your portable wiki on a stick, all you have to do is double click on &#039;&#039;&#039;mowes.exe&#039;&#039;&#039; in the root of your USB drive.&lt;br /&gt;
&lt;br /&gt;
===Run from a Batch File===&lt;br /&gt;
If you&#039;d like create an appropriately-named [[batch]] file to launch &#039;&#039;&#039;mowes.exe&#039;&#039;&#039; instead:&lt;br /&gt;
&lt;br /&gt;
BRWiki.cmd (for example) might contain:&lt;br /&gt;
  mowes.exe&lt;br /&gt;
&lt;br /&gt;
===AutoRun===&lt;br /&gt;
You may like your wiki to automatically pop up when you insert your thumb drive into a computer.  To do that you&#039;ll need to make an [[AutoRun.inf]] file and place it in the root directory of your thumb drive.  The AutoRun.inf file is just a regular text file and should contain the following:&lt;br /&gt;
&lt;br /&gt;
 [AutoRun.inf]&lt;br /&gt;
  Open=mowes.exe&lt;br /&gt;
&lt;br /&gt;
It may contain more, but that&#039;s the bare minimum.&lt;br /&gt;
&lt;br /&gt;
===Location===&lt;br /&gt;
Perhaps you don&#039;t want your wiki on a stick to be stored in the root of your flash drive. Or maybe you don&#039;t want it on a flash drive at all. Have it your way! You can put your wiki anywhere you want- even at the end of a ridiculously long path in My Documents on your hard drive. Or perhaps you want it on your flash drive, but in a folder of it&#039;s own, separate from all of your other files and folders. It will be fine there too. Just make sure to alter any Autorun or Batch files that call the wiki. That&#039;s all you have to do!&lt;br /&gt;
&lt;br /&gt;
==FAQ==&lt;br /&gt;
&#039;&#039;&#039;Q.&#039;&#039;&#039; What should I export from the BR Wiki?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A.&#039;&#039;&#039; &lt;br /&gt;
Always get:&lt;br /&gt;
*the [[:Category:Templates|Templates category]]&lt;br /&gt;
Additionally:&lt;br /&gt;
*Category &#039;&#039;&#039;Error Codes&#039;&#039;&#039;&lt;br /&gt;
*Category &#039;&#039;&#039;Widgets&#039;&#039;&#039;&lt;br /&gt;
*Category &#039;&#039;&#039;BR Manual&#039;&#039;&#039;&lt;br /&gt;
*[[Special:Allpages]] contains a list of all the pages, go there and copy anything you want right into [[Special:Export]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; You can&#039;t take everything in one export because it will exceed the maximum import size on your local wiki.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q.&#039;&#039;&#039; Can I edit my wiki on a stick?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A.&#039;&#039;&#039; Yes, you can, but be aware that all changes you make to your wiki on a stick will be lost forever just as soon as you import additional data from the BR Wiki.  When programming in a jungle, you should log the desired changes, and when you are back to civilization (internet accessible) make those changes to the BR Wiki.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Q.&#039;&#039;&#039; Page not found&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A.&#039;&#039;&#039; If you get a Page not found error in your browser than it&#039;s probably because the IP address hasn&#039;t populated and cached everywhere yet... Simply, wait a few seconds and press F5/Refreash.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Utilities Third Party]]&lt;br /&gt;
[[Category:How To]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Lexi&amp;diff=3453</id>
		<title>Lexi</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Lexi&amp;diff=3453"/>
		<updated>2013-06-19T03:08:26Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Lexi&#039;&#039;&#039;, the &#039;&#039;&#039;BR! Lexical Preprocessor&#039;&#039;&#039; is a system for integrating [[BR]] with your favorite [[third party editor]]. Initially Lexi only supported only [[MyEdit]], but it is also being used successfully with [[Notepad++]] and is very likely to work with any text editor that supports customizable user tools.&lt;br /&gt;
&lt;br /&gt;
If you use Lexi, you can edit your [[BR Programs]] [[#No Line Numbers|Without Line Numbers]]. This frees you up to copy and paste code, rearrange code, and add and edit code without having to worry about or manually change any line numbers.  Lexi adds and changes and manages your [[line numbers]] for you automatically, when you &amp;quot;compile&amp;quot; your programs into .BR files.&lt;br /&gt;
&lt;br /&gt;
But Lexi also does a lot more.  By preprocessing your [[source code|code]] before it is passed on to BR, Lexi gives you, the programmer, access to many useful features not normally found in BR.&lt;br /&gt;
&lt;br /&gt;
Lexi also gives you access to the [[#SELECT CASE|SELECT CASE]] statement and the [[#DEFINE]] statement, common in other languages.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
===MyEdit (BR Edition)===&lt;br /&gt;
Lexi can be used to automatically convert between BRS and BR files from within MyEdit. This can make your Editing life much easier. Lexi works with ALL versions of BR. However it requires a version of MyEdit dated [[October 20]], [[2006]] or later.&lt;br /&gt;
&lt;br /&gt;
The latest version of Lexi can be found at [http://www.sageax.com/downloads/Lexi.zip]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Instructions====&lt;br /&gt;
&lt;br /&gt;
To install Lexi, follow the following steps.&lt;br /&gt;
&lt;br /&gt;
=====Automatic Installation=====&lt;br /&gt;
&lt;br /&gt;
*The Automatic Installation process requires a version of MyEdit dated [[March 5]], [[2010]] or later.&lt;br /&gt;
&lt;br /&gt;
#) Unzip Lexi.zip into &amp;quot;C:\Lexi&amp;quot;. You must use this directory in order for the automatic installation to work.&lt;br /&gt;
#) Copy your personal [[brserial.dat]] file into this directory (C:\Lexi).&lt;br /&gt;
#) Launch MyEdit.&lt;br /&gt;
#) Select Import User Tools. Select the &amp;quot;Lexi.mut&amp;quot; file that came in Lexi.zip.&lt;br /&gt;
&lt;br /&gt;
That&#039;s all there is to it.&lt;br /&gt;
&lt;br /&gt;
=====Manual Installation=====&lt;br /&gt;
&lt;br /&gt;
#) Unzip Lexi.zip into its own directory.&lt;br /&gt;
#) Copy your personal BRSerial.dat file into this directory.&lt;br /&gt;
#) Launch MyEdit.&lt;br /&gt;
#) Go to the Tools Menu, and then select &amp;quot;Configure User Tools&amp;quot;.&lt;br /&gt;
#) Select &amp;quot;Add&amp;quot;&lt;br /&gt;
#) Enter the following information (Replace C:\Lexi\ with the appropriate folder), and Click OK to add the &amp;quot;Compile&amp;quot; tool.&lt;br /&gt;
&lt;br /&gt;
  Menu Item Name: Compile BR Program&lt;br /&gt;
  Application/Command: C:\Lexi\ConvStoO.cmd&lt;br /&gt;
  Working Folder: C:\Lexi\&lt;br /&gt;
  Command Line Parameters: %%np_name %%npne_name &amp;quot;%%name&amp;quot; &amp;quot;%%folder&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
There are six other Tools you can add to the MyEdit user tools menu that give you additional abilities for working with BR Source code. To add additional tools, repeat steps 5 and 6 above substituting information from the &amp;quot;Available Functions&amp;quot; table below.&lt;br /&gt;
&lt;br /&gt;
That&#039;s all there is to it. Now, if you load a .BR file in MyEdit, you can select the &amp;quot;Extract Source&amp;quot; tool.&lt;br /&gt;
The file will be converted to a .BRS file and the new one will be loaded in MyEdit. If you&lt;br /&gt;
load a .BRS file, you can select the &amp;quot;Compile&amp;quot; tool, and the file will automatically be&lt;br /&gt;
&amp;quot;compiled&amp;quot; into a .BR file for you. Then simply load BR and test your new program.&lt;br /&gt;
&lt;br /&gt;
This works with all versions of BR.&lt;br /&gt;
&lt;br /&gt;
====Available Functions====&lt;br /&gt;
&lt;br /&gt;
{| border=0&lt;br /&gt;
!Menu Item&lt;br /&gt;
!Application&lt;br /&gt;
!Parameters&lt;br /&gt;
|-&lt;br /&gt;
|Compile BR Program&lt;br /&gt;
|ConvStoO.cmd&lt;br /&gt;
|%%np_name %%npne_name &amp;quot;%%name&amp;quot; &amp;quot;%%folder&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|Extract Source Code&lt;br /&gt;
|ConvOtoS.cmd&lt;br /&gt;
|%%np_name %%npne_name &amp;quot;%%name&amp;quot; &amp;quot;%%folder&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|Debug BR Program*&lt;br /&gt;
|DebugBR.cmd&lt;br /&gt;
|%%np_name %%npne_name &amp;quot;%%name&amp;quot; &amp;quot;%%folder&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|Extract Source Code and Strip Line Numbers&lt;br /&gt;
|ConvOSNL.cmd&lt;br /&gt;
|%%np_name %%npne_name &amp;quot;%%name&amp;quot; &amp;quot;%%folder&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|Add Line Numbers&lt;br /&gt;
|AddLN.cmd&lt;br /&gt;
|%%np_name %%npne_name &amp;quot;%%name&amp;quot; &amp;quot;%%folder&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|Strip Line Numbers&lt;br /&gt;
|StripLN.cmd&lt;br /&gt;
|%%np_name %%npne_name &amp;quot;%%name&amp;quot; &amp;quot;%%folder&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|Run BR Program&lt;br /&gt;
|RunBR.cmd&lt;br /&gt;
|%%np_name %%npne_name &amp;quot;%%name&amp;quot; &amp;quot;%%folder&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* Debug BR Program requires that you have a copy of [[brnative.exe]] in the appropriate version sitting in your application folder. This may not be possible in all situations. Use Compile BR Program in situations where you cannot use Debug BR Program.&lt;br /&gt;
&lt;br /&gt;
===Notepad++===&lt;br /&gt;
Users such as [[User:Bowman]] are currently using Lexi from within [[Notepad++]].  However he has not yet been kind enough to share his setup process.  If you implement Lexi into your Notepad++ installation please add some instructions here.  If you can&#039;t figure it out I&#039;d suggest contacting [[User:Bowman]] for assistance.&lt;br /&gt;
&lt;br /&gt;
====Instructions====&lt;br /&gt;
These instructions assume Lexi &lt;br /&gt;
&lt;br /&gt;
=====Automatic Installation=====&lt;br /&gt;
Probably the easiest way to install Lexi tools into Notepad++ is to add the following lines to your shortcuts.xml file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;Command name=&amp;quot;BR!s - Compile&amp;quot; Ctrl=&amp;quot;yes&amp;quot; Alt=&amp;quot;yes&amp;quot; Shift=&amp;quot;yes&amp;quot; Key=&amp;quot;73&amp;quot;&amp;gt;C:\Lexi\ConvStoO.cmd &amp;amp;quot;$(FULL_CURRENT_PATH)&amp;amp;quot;&amp;lt;/Command&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;Command name=&amp;quot;BR!s - Stip line numbers&amp;quot; Ctrl=&amp;quot;yes&amp;quot; Alt=&amp;quot;yes&amp;quot; Shift=&amp;quot;yes&amp;quot; Key=&amp;quot;73&amp;quot;&amp;gt;C:\Lexi\StripLN.cmd &amp;amp;quot;$(FULL_CURRENT_PATH)&amp;amp;quot;&amp;lt;/Command&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;Command name=&amp;quot;BR!s - Add line numbers&amp;quot; Ctrl=&amp;quot;yes&amp;quot; Alt=&amp;quot;yes&amp;quot; Shift=&amp;quot;yes&amp;quot; Key=&amp;quot;73&amp;quot;&amp;gt;C:\Lexi\AddLN.cmd &amp;amp;quot;$(FULL_CURRENT_PATH)&amp;amp;quot;&amp;lt;/Command&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Manual Installation=====&lt;br /&gt;
&lt;br /&gt;
Add three user controls by choosing Run&amp;gt;Run... (enter the first line) and click Save, then select the remaining two lines.  Do these steps for each of the Lexi utilities listed here.&lt;br /&gt;
&lt;br /&gt;
 BRS - Line numbers - Remove&lt;br /&gt;
 C:\Lexi\StripLN.cmd &amp;quot;$(FULL_CURRENT_PATH)&amp;quot;&lt;br /&gt;
 Alt+8&lt;br /&gt;
&lt;br /&gt;
 BRS - Line numbers - Add&lt;br /&gt;
 C:\Lexi\AddLN.cmd &amp;quot;$(FULL_CURRENT_PATH)&amp;quot;&lt;br /&gt;
 Alt+Shift+8&lt;br /&gt;
&lt;br /&gt;
 BR!s - Compile&lt;br /&gt;
 C:\Lexi\ConvStoO.cmd &amp;quot;$(FULL_CURRENT_PATH)&amp;quot;&lt;br /&gt;
&lt;br /&gt;
====Available Functions====&lt;br /&gt;
{| border=0&lt;br /&gt;
!Menu Item&lt;br /&gt;
!The Program To Run&lt;br /&gt;
|-&lt;br /&gt;
|BRS - Compile&lt;br /&gt;
|C:\Lexi\ConvStoO.cmd &amp;quot;$(FULL_CURRENT_PATH)&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|BRS - Line numbers - Add&lt;br /&gt;
|C:\Lexi\AddLN.cmd &amp;quot;$(FULL_CURRENT_PATH)&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|BRS - Line numbers - Remove&lt;br /&gt;
|C:\Lexi\StripLN.cmd &amp;quot;$(FULL_CURRENT_PATH)&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Potentially other functions could be made available but have not yet been enhanced to work with the single full path parameter.  The enhanced batch files (listed above) could serve as an example of how this is done - If you&#039;re feeling spunky.&lt;br /&gt;
&lt;br /&gt;
* These installation instructions assumes the enhancement of 1 parameter passing (as opposed to 4) was included in your distribution.&lt;br /&gt;
&lt;br /&gt;
===All Third Party Editors===&lt;br /&gt;
&lt;br /&gt;
====Tips====&lt;br /&gt;
*Inside the \Lexi\ folder you will find a copy of BR renamed to brnative.exe. It works better if this brnative.exe is the same version of BR that you are using in your programs. So copy your BR to this folder and replace brnative.exe with it.&lt;br /&gt;
*If you are having some trouble &amp;quot;Extracting Source&amp;quot; and you installed MyEdit to a custom location you will need to modify the file ConvOtoS.cmd to point to the proper location of MyEdit.exe. Load it in a text editor and you&#039;ll see what I mean.&lt;br /&gt;
*There is an additional tool called DebugBR.cmd. This only works if there is a working BR file called brnative.exe in the same folder as your program files. You add it to the list the same way as you did the other tools above.&lt;br /&gt;
&lt;br /&gt;
== Function Reference ==&lt;br /&gt;
&lt;br /&gt;
Lexi gives you access to a number of different abilities from other programs, designed to make your source code editing life easier. When you send a source file to BR using Lexi, Lexi preprocesses your source code, adding line numbers, and interpreting other &amp;quot;precompiler directives&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=== No Line Numbers ===&lt;br /&gt;
&lt;br /&gt;
Working with No [[Line Numbers]] is easy, when you have Lexi to help.&lt;br /&gt;
&lt;br /&gt;
You load your files using MyEdit, and you work with them as Source Code files. If you are editing a file in MyEdit that has line numbers in it, you can save the document and select the &amp;quot;Strip Line Numbers&amp;quot; user tool. This will launch BR, use it to strip out the line numbers, and reload your program in MyEdit. You make the changes you want while the line numbers are gone, and when you choose the &amp;quot;Compile&amp;quot; user tool or the &amp;quot;Add Line Numbers&amp;quot; user tool, the line numbers are added back to your program. If you choose the &amp;quot;Compile&amp;quot; tool, the line numbers are added, and your source code file is saved as a .BR file.&lt;br /&gt;
&lt;br /&gt;
  43900  ! #Autonumber# 43900,10&lt;br /&gt;
  43910  DoesLayoutExist: ! Return true if layout exists in the layouts folder&lt;br /&gt;
  43920        def library FnDoesLayoutExist(layout$;LayoutPath$*255)&lt;br /&gt;
  43930           let Fnsettings(Layoutpath$) !:&lt;br /&gt;
                  fnDoesLayoutExist = exists(LayoutPath$&amp;amp;Filename$)&lt;br /&gt;
  43940        fnend&lt;br /&gt;
&lt;br /&gt;
The above code gets turned into the following code when line numbers are stripped. When they are added back in, it gets turned back into the code above again.&lt;br /&gt;
&lt;br /&gt;
  ! #Autonumber# 43900,10&lt;br /&gt;
  DoesLayoutExist: ! Return true if layout exists in the layouts folder&lt;br /&gt;
        def library FnDoesLayoutExist(layout$;LayoutPath$*255)&lt;br /&gt;
           let Fnsettings(Layoutpath$) !:&lt;br /&gt;
           fnDoesLayoutExist = exists(LayoutPath$&amp;amp;Filename$)&lt;br /&gt;
        fnend&lt;br /&gt;
&lt;br /&gt;
=== AutoNumber ===&lt;br /&gt;
&lt;br /&gt;
The #AutoNumber# precompiler directive directs the Line Number Add routine to use certian line numbers in your code.&lt;br /&gt;
&lt;br /&gt;
Without the #AutoNumber# precompiler directive, Lexi adds line numbers starting with line number 00001 and counting by 1s.&lt;br /&gt;
&lt;br /&gt;
  ! This Example Is Quite Simple:&lt;br /&gt;
     let Fnupdatefiledropdown ! We Run This No Matter What Happens. It Builds The Combo Box Dropdown List&lt;br /&gt;
  !&lt;br /&gt;
     if Trim$(_Post$(1))=&amp;quot;&amp;quot; then ! If The User Did Not Select A File Layout From The List Then&lt;br /&gt;
        let Fnreadlayoutfolder ! Display The File Layout List In A Table&lt;br /&gt;
     else&lt;br /&gt;
        let Fnreadfileio(Trim$(_Post$(1))) ! But If They Did Select A File, Then Show It&lt;br /&gt;
     end if&lt;br /&gt;
     stop&lt;br /&gt;
&lt;br /&gt;
becomes&lt;br /&gt;
&lt;br /&gt;
  00001 ! This Example Is Quite Simple:&lt;br /&gt;
  00002    let Fnupdatefiledropdown ! We Run This No Matter What Happens. It Builds The Combo Box Dropdown List&lt;br /&gt;
  00003 !&lt;br /&gt;
  00004    if Trim$(_Post$(1))=&amp;quot;&amp;quot; then ! If The User Did Not Select A File Layout From The List Then&lt;br /&gt;
  00005       let Fnreadlayoutfolder ! Display The File Layout List In A Table&lt;br /&gt;
  00006    else&lt;br /&gt;
  00007       let Fnreadfileio(Trim$(_Post$(1))) ! But If They Did Select A File, Then Show It&lt;br /&gt;
  00008    end if&lt;br /&gt;
  00009    stop&lt;br /&gt;
&lt;br /&gt;
The idea is that you maintain your programs in source files, and so it doesn&#039;t matter what your line numbers are.&lt;br /&gt;
&lt;br /&gt;
However, most BR Vendors do not maintain their programs as source files. They maintain them as .BR or .WB files, and the line numbers are important.&lt;br /&gt;
&lt;br /&gt;
To use the #AutoNumber# precompiler directive, all you have to do is place simple comments in your code that say:&lt;br /&gt;
&lt;br /&gt;
  ! #AutoNumber# LineNum,Increment&lt;br /&gt;
&lt;br /&gt;
Then, when Lexi is adding line numbers, and it finds one of these lines, Lexi tries to set the line number of the current line to the line number you specified. Thereafter, until it reaches the next #AutoNumber# statement, it counts by the Increment you gave it.&lt;br /&gt;
&lt;br /&gt;
In this way, its easy to give your functions each their own line number space, and still retain the ability to edit without having to worry about line numbers.&lt;br /&gt;
&lt;br /&gt;
With the #AutoNumber# statement,&lt;br /&gt;
&lt;br /&gt;
  ! #Autonumber# 16000,10&lt;br /&gt;
  DefineModes: ! Define the input spec modes&lt;br /&gt;
  def fnDefineInputModes&lt;br /&gt;
     dim InputAttributesMode&lt;br /&gt;
     dim InputFieldlistMode&lt;br /&gt;
     dim InputEditorMode&lt;br /&gt;
     dim InputEditorMoveMode&lt;br /&gt;
     dim InputDebugMode&lt;br /&gt;
  &lt;br /&gt;
     let InputAttributesMode=1&lt;br /&gt;
     let InputFieldlistMode=2&lt;br /&gt;
     let InputEditorMode=3&lt;br /&gt;
     let InputEditorMoveMode=4&lt;br /&gt;
     let InputDebugMode=5&lt;br /&gt;
  fnend&lt;br /&gt;
&lt;br /&gt;
becomes&lt;br /&gt;
&lt;br /&gt;
  16000 ! #Autonumber# 16000,10&lt;br /&gt;
  16010 DefineModes: ! Define the input spec modes&lt;br /&gt;
  16020 def fnDefineInputModes&lt;br /&gt;
  16030    dim InputAttributesMode&lt;br /&gt;
  16040    dim InputFieldlistMode&lt;br /&gt;
  16050    dim InputEditorMode&lt;br /&gt;
  16060    dim InputEditorMoveMode&lt;br /&gt;
  16070    dim InputDebugMode&lt;br /&gt;
  16080 !&lt;br /&gt;
  16090    let InputAttributesMode=1&lt;br /&gt;
  16100    let InputFieldlistMode=2&lt;br /&gt;
  16110    let InputEditorMode=3&lt;br /&gt;
  16120    let InputEditorMoveMode=4&lt;br /&gt;
  16130    let InputDebugMode=5&lt;br /&gt;
  16140 fnend&lt;br /&gt;
&lt;br /&gt;
For this reason, when you are removing line numbers from your programs, it is sometimes a good idea to populate them with #AutoNumber# comments first, to preserve your original line number structure as much as possible.&lt;br /&gt;
&lt;br /&gt;
If the line numbers program detects that your #AutoNumber# comments are not in numerical order, or if there is not enough numbers between them to accomodate all your lines, it will generate an error and stop processing your program. At that time you should type clear, and then system to return to your editor, and fix the #AutoNumber# statements there. After you fix the problem, Save your source code again, and compile.&lt;br /&gt;
&lt;br /&gt;
=== DEFINE ===&lt;br /&gt;
&lt;br /&gt;
The #DEFINE# Precompiler Directive will tell The Line Number generation system that you have made a constant.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  !. &amp;quot;#Define# &amp;lt;nowiki&amp;gt;[[ScreenControls]]&amp;lt;/nowiki&amp;gt; = &amp;quot;mat ControlName$, mat FieldName$, mat Description$, mat VPosition, mat HPosition, mat FieldType$&amp;quot;&lt;br /&gt;
&lt;br /&gt;
The above example will set up a precompiler Constant called &amp;lt;nowiki&amp;gt;[[ScreenControls]]&amp;lt;/nowiki&amp;gt;. Now, everywhere in your program that you use the text &amp;lt;nowiki&amp;gt;[[ScreenControls]]&amp;lt;/nowiki&amp;gt; will be replaced by &amp;quot;mat ControlName$, mat FieldName$, mat Description$, mat VPosition, mat HPosition, mat FieldType$&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;.&amp;quot; will force BR to not change the capitalization of your comments.&lt;br /&gt;
&lt;br /&gt;
   ! #AutoNumber# 14000,10&lt;br /&gt;
   EditScreen: ! Main Screen Designer&lt;br /&gt;
   def fnEditScreen(fScreenIO, fScreenFld, ScreenName$, mat ScreenIO$, mat ScreenIO,&amp;lt;nowiki&amp;gt;[[ScreenControls]]&amp;lt;/nowiki&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
This function definition changes to contain the full list of arrays that are responsible for Screen Control information in the ScreenIO library, each time the program is compiled.&lt;br /&gt;
&lt;br /&gt;
When the source code is pulled back out and the line numbers are stripped, the substitute statements revert back to their original values.&lt;br /&gt;
&lt;br /&gt;
=== SELECT CASE ===&lt;br /&gt;
&lt;br /&gt;
We have implemented SELECT CASE as a precompiler directive. This means, when editing your programs with no line numbers, you can write SELECT CASE (SWITCH in C/C++) statements using the following syntax, and it will automatically be turned into IF THEN ELSEIF statements when it gets to BR.&lt;br /&gt;
&lt;br /&gt;
  ! #Autonumber# 16000,10&lt;br /&gt;
  PreformInput: ! Preform main input operation&lt;br /&gt;
  def fnPreformInput(&amp;amp;Mode,Control,mat ScreenIO$,mat ScreenIO;___,Window)&lt;br /&gt;
     #SELECT# Mode #CASE# InputAttributesMode&lt;br /&gt;
        let Window=fnGetAttributesWindow&lt;br /&gt;
        let fnGetAttributeSpec(mat InputSpec$,mat InputData$,mat InputSubs)&lt;br /&gt;
        rinput #Window, fields mat InputSpec$ : mat InputData$&lt;br /&gt;
  &lt;br /&gt;
     #CASE# InputFieldlistMode&lt;br /&gt;
        let Window=fnGetFieldsWindow&lt;br /&gt;
        let fnGetFieldsSpec(InputSpec$)&lt;br /&gt;
        rinput #Window, fields InputSpec$ : InputData&lt;br /&gt;
  &lt;br /&gt;
     #CASE# InputDebugMode&lt;br /&gt;
        let Window=fnGetDebugWindow&lt;br /&gt;
        let fnGetFieldsSpec(InputSpec$)&lt;br /&gt;
        rinput #Window, fields InputSpec$ : InputData&lt;br /&gt;
  &lt;br /&gt;
     #End Select#&lt;br /&gt;
  fnend&lt;br /&gt;
&lt;br /&gt;
Gets translated into this:&lt;br /&gt;
&lt;br /&gt;
  16000  ! #Autonumber# 16000,10&lt;br /&gt;
  16010  PreformInput: ! Preform main input operation&lt;br /&gt;
  16020  def fnPreformInput(&amp;amp;Mode,Control,mat ScreenIO$,mat ScreenIO;___,Window)&lt;br /&gt;
  16030     IF  Mode  =  InputAttributesMode THEN  ! #SELECT# Mode #CASE# InputAttributesMode&lt;br /&gt;
  16040        let Window=fnGetAttributesWindow&lt;br /&gt;
  16050        let fnGetAttributeSpec(mat InputSpec$,mat InputData$,mat InputSubs)&lt;br /&gt;
  16060        rinput #Window, fields mat InputSpec$ : mat InputData$&lt;br /&gt;
  16070  !&lt;br /&gt;
  16080     ELSE IF  Mode  =  InputFieldlistMode THEN  ! #CASE# InputFieldlistMode&lt;br /&gt;
  16090        let Window=fnGetFieldsWindow&lt;br /&gt;
  16100        let fnGetFieldsSpec(InputSpec$)&lt;br /&gt;
  16110        rinput #Window, fields InputSpec$ : InputData&lt;br /&gt;
  16120  !&lt;br /&gt;
  16130     ELSE IF  Mode  =  InputDebugMode THEN  ! #CASE# InputDebugMode&lt;br /&gt;
  16140        let Window=fnGetDebugWindow&lt;br /&gt;
  16150        let fnGetFieldsSpec(InputSpec$)&lt;br /&gt;
  16160        rinput #Window, fields InputSpec$ : InputData&lt;br /&gt;
  16170  !&lt;br /&gt;
  16180     END IF  ! #End Select#&lt;br /&gt;
  16190  fnend&lt;br /&gt;
&lt;br /&gt;
You may notice the comments that appear at the end of your IF THEN statements. The comments are created automatically by the &amp;quot;Add Line Numbers&amp;quot; routine when it translates the SELECT CASE statement into IF THEN ELSEIF statements. The purpose of the comments is so that the &amp;quot;Strip Line Numbers&amp;quot; routine can change them back into a SELECT CASE statement so that your code appears correct on the editor/line-number-free side.&lt;br /&gt;
&lt;br /&gt;
=== Spacing ===&lt;br /&gt;
&lt;br /&gt;
As you can see from the above examples, any blank spaces you insert into your programs are turned automatically into blank comment lines. This is to preserve the spacing and look and feel of your program on the editor/line-number-free side.&lt;br /&gt;
&lt;br /&gt;
== Considerations ==&lt;br /&gt;
&lt;br /&gt;
=== L##### labels ===&lt;br /&gt;
Because Lexi strips the line numbers before you edit your document, it would easily cause a problem if you had any hard coded line number references, because your line numbers change all the time and those references aren&#039;t automatically updated. Therefore, before it strips line numbers from any BR program, Lexi loads the program in BR and executes the [[RENUM]] LABELS_ONLY command. This command replaces all your hard coded goto references with labels that are L##### where ##### is the line number.&lt;br /&gt;
&lt;br /&gt;
That way you are free to edit your document without worrying about the line numbers, and later, when you add in new line numbers, your program still works.&lt;br /&gt;
&lt;br /&gt;
If you have accidentally placed L##### labels in your code and you need them removed, contact [[mailto:gabriel.bakker@gmail.com Gabriel]].  He has written a program to remove them.&lt;br /&gt;
&lt;br /&gt;
The L##### labels do not harm your code - it will work exactly as before. However, I understand sometimes it can be confusing if something like this happens to your code and there is a tool to change them back.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
One other note about L##### labels: If the &amp;quot;Add Line Numbers&amp;quot; routine detects any of these labels in your code, it will use them as clues as to what your original line numbers were, and it will match the new line numbers as closely as possible to the old one. This is done for your comfort as you edit your programs, just in case you still edit them in BR and use the line numbers. I wanted your programs to remain as unchanged by the linkage as possible.&lt;br /&gt;
&lt;br /&gt;
=== Save Source Code ===&lt;br /&gt;
It is of vital importance that you save your source code before executing any of the user tools. If you fail to save your source code before using a user tool, the tool will operate on the old version of the file that it finds on the disk, and when the conversion is complete and the new file is reloaded in MyEdit, all your changes will be lost. You can&#039;t undo it because MyEdit thinks you have loaded a whole new file.&lt;br /&gt;
&lt;br /&gt;
Please be careful when using this.&lt;br /&gt;
&lt;br /&gt;
=== PROC NOECHO ===&lt;br /&gt;
For anyone who has used Lexi in the past, it used to scroll through the contents of your program as it was adding or removing line numbers, due to the process of converting your source file into a compiled BR program. Depending on the size of the program and the speed of your system, this process may have taken a long time.&lt;br /&gt;
&lt;br /&gt;
The latest version of Lexi has been updated with PROC NOECHO to disable this printout and greatly improve the speed of compiling your programs. As a result of PROC NOECHO, if there are any compile time errors in your code, you will not be able to see the line that caused the problem, until you press F2. Just remember, if you run into a problem compiling your screen, press F2 to see the offending line.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Disclaimer==&lt;br /&gt;
&lt;br /&gt;
[[User:Gabriel|Gabriel Bakker]] and [[Sage AX]] are not responsible for anything that happens to your BR programs or data as a result of using this or any other tool we create.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Utilities_Third_Party]]&lt;br /&gt;
[[Category:How To]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=ScreenIO_Library&amp;diff=3451</id>
		<title>ScreenIO Library</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=ScreenIO_Library&amp;diff=3451"/>
		<updated>2013-06-19T03:08:25Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;ScreenIO Library&#039;&#039;&#039; is a Rapid Application Design tool that enables Sage AX to create complete custom programs for a fraction of the cost of traditional development. For example, a fully functional File Maintenance program can now be created for $300. A zoom function or any other &amp;quot;single screen&amp;quot; program can be created for $150.&lt;br /&gt;
&lt;br /&gt;
These &amp;quot;screen functions&amp;quot; integrate directly with your existing database and can be implemented as a standard BR library anywhere in your existing software. Some of our customers have placed them on tabs in already existing &amp;quot;tabbed windows&amp;quot; (or new tabbed windows). Some of our customers used them to quickly spruce up the look and feel of programs designed and written for older versions of BR, with modern new gui controls.&lt;br /&gt;
&lt;br /&gt;
Just about any business application can be designed faster, cheaper, and easier using ScreenIO, than ever before. You can even build entire application suites out of &amp;quot;Screen Functions&amp;quot;. Sage recently wrote our entire internal accounting system using &amp;quot;screen function&amp;quot; technology, in just a couple of weeks.&lt;br /&gt;
&lt;br /&gt;
The ScreenIO Library is a sister library to the [[FileIO Library]]. The ScreenIO library builds upon and requires the FileIO library in order to run. &lt;br /&gt;
&lt;br /&gt;
The ScreenIO Library is a third party developer tool created and marketed by Sage AX to the BR programmer.&lt;br /&gt;
&lt;br /&gt;
== Bookmarks ==&lt;br /&gt;
&lt;br /&gt;
Before we get any farther, if you&#039;re here for help with ScreenIO, here&#039;s a short list of common reference links:&lt;br /&gt;
&lt;br /&gt;
[[#ScreenIO Runtime Engine Library Functions|ScreenIO&#039;s fnFm Parameter List]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[#ScreenIO Events|Custom Function - Events]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[#Writing Screen Helper Functions|Custom Function - Parameters]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[#Keyboard Reference (Undo/Redo, Copy/Cut/Paste and more)|Keyboard Reference]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[#Working with the ScreenIO Loading Icon|Animations]]&amp;lt;br&amp;gt;&lt;br /&gt;
[[#ExitMode|ExitMode]]&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Using ScreenIO Screens ==&lt;br /&gt;
&lt;br /&gt;
This section of the documentation deals with all of the ways to make use of your screens created with the ScreenIO system.&lt;br /&gt;
&lt;br /&gt;
=== Screen Functions ===&lt;br /&gt;
&lt;br /&gt;
==== What is a Screen Function? ====&lt;br /&gt;
&lt;br /&gt;
A Screen Function is a complete self contained program, that can be chained to, procced to, run as a regular program, or even run as a library from right in the middle of your existing program.&lt;br /&gt;
&lt;br /&gt;
Screens are Modular and Reusable. That means you can create a screen for selecting a customer from a listview on the screen. This &amp;quot;Listview Screen&amp;quot; can also have buttons that chain to other screens, such as an Add/Edit Screen.&lt;br /&gt;
&lt;br /&gt;
Now you have a complete FM program in two screens, for maintaining the customer file. But wait, what if you need a &amp;quot;Customer Selection&amp;quot; listview in your other programs? No problem, the same &amp;quot;Screen Function&amp;quot; program that was run before as your Customer FM, can also be run as a library function, as your Customer Selection screen.&lt;br /&gt;
&lt;br /&gt;
So a Screen Function is more than a program. Its a program and a library, a gui, a complete software generation system, and an easy way to write beautiful software in BR that can be implemented again and again in your programs.&lt;br /&gt;
&lt;br /&gt;
A Screen Function is a totally modular object. Its easy to add a screen to an existing program, or to another screen. By combining multiple screens you can create truly amazing effects.&lt;br /&gt;
&lt;br /&gt;
By Combining four screens together, we can even write File Maintenance programs that work on two data files simultaneously, with a parent/child relationship!&lt;br /&gt;
&lt;br /&gt;
==== How does it work? ====&lt;br /&gt;
&lt;br /&gt;
Using our powerful ScreenIO Programming System, we create the Screen and save it in an internal data file that keeps track of what data needs to be displayed where on the screen, where it needs to be saved on the disk, and what we want to do with it. We can even embed function calls and business logic directly in the screens. When we &amp;quot;compile&amp;quot; the screens, a screen helper library is created with all the custom function code that needs to run from your screen. This helper library also serves as the program you can use to run your screens.&lt;br /&gt;
&lt;br /&gt;
By keeping the screen layout in data files, it becomes easy to modify and easy to maintain. By making the screens run as library functions, they become easy to implement anywhere in your existing programs. All you have to do is create the library linkage and call the program with the following two lines of BR code:&lt;br /&gt;
&lt;br /&gt;
  LIBRARY &amp;quot;screenio&amp;quot; : fnfm$&lt;br /&gt;
  let Result$=fnfm$(&amp;quot;scrnname&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
Result$ can be queried to see what the user did in the screen. A listview selection screen will return the record selected. An Add/Edit screen will directly write the results to the data file for you, and return the key to this new record in Result$. If the user cancels, Result$ will be empty.&lt;br /&gt;
&lt;br /&gt;
==== What can a Screen Function Do? ====&lt;br /&gt;
&lt;br /&gt;
A Screen Function can do many things. A Screen Function right now generally fits into three categories:&lt;br /&gt;
&lt;br /&gt;
  1. A Listview Screen Function&lt;br /&gt;
  2. An Add/Edit Screen Function&lt;br /&gt;
  3. A Menu/Simple Screen Function&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Listview Screen Function =====&lt;br /&gt;
&lt;br /&gt;
A Listview Screen Function is a Screen Function that is tied to a data file (through fileIO) and has no editable text controls on it, and has a Listview on it somewhere.&lt;br /&gt;
&lt;br /&gt;
A Listview Screen Function is now the very easiest way to implement 2D Controls in your BR programs. A ListView Screen Function displays all or some of the records in a data file and allows the user to select one. In your Listview screen, you may also have a link to the add/edit screen for the same data file, creating a basic File Maintenance program. You can use your Listview Screen anywhere that you would like the user to select a record from the ListView Screen&#039;s Target File. If it is tied to an Add/Edit screen, you may also use it as the File Maintenance program for that screen. You can use the same screen in multiple ways.&lt;br /&gt;
&lt;br /&gt;
===== Add/Edit Screen Function =====&lt;br /&gt;
&lt;br /&gt;
An Add/Edit Screen Function is a screen function that is tied to a data file (through fileIO) and has editable text controls on it, and no Listivew control on it anywhere. An Add/Edit screen can be passed a key, which will cause it to act as an Edit Screen Function, telling ScreenIO to edit the record who&#039;s key was passed in. If the Add/Edit screen is not passed in a key, it will act as an Add Screen Function, telling ScreenIO to Add a new record to the data file.&lt;br /&gt;
&lt;br /&gt;
An Add/Edit Screen Function is the easiest way to create any sort of user interface asking for specific data from a customer.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== A Menu/Simple Screen Function =====&lt;br /&gt;
&lt;br /&gt;
A Menu/Simple Screen Function is a screen function that is not tied to any data file. This sort of screen is very limited in functionality. The primary purpose of using such a screen is to create a menu of buttons that call other screens or other programs or library functions or parts of your code.&lt;br /&gt;
&lt;br /&gt;
A Menu/Simple screen function cannot change any data on disk because it is not tied to a data file. It is also not possible to get a lot of information back from the user in a Simple Screen Function, because instead of returning a key to a record in a data file that was edited (like an Add/Edit screen function would), a Menu/Simple screen is limited to returning a 255 byte string for its return value.&lt;br /&gt;
&lt;br /&gt;
==== Limitations ====&lt;br /&gt;
&lt;br /&gt;
===== No combination Listview/Add/Edit screens =====&lt;br /&gt;
&lt;br /&gt;
It is not possible to make a screen that contains both a Listview, and Add/Edit capabilities in the same screen. When the user changes selection on a Listview, this changes the current record that the screen is using. If they were attempting to change a record on a combination ListView/Add/Edit screen, their changes would get lost each time the Listview selection changes. For that reason, if you wish to have both a Listview and some record selection going on at the same time, you will need to have two screens and tie them to each other.&lt;br /&gt;
&lt;br /&gt;
It is much better to stick to a single purpose for each Screen Function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Future ====&lt;br /&gt;
&lt;br /&gt;
The following features are not currently available in screens, but will be soon:&lt;br /&gt;
&lt;br /&gt;
===== Grids =====&lt;br /&gt;
&lt;br /&gt;
Grids are not currently supported in ScreenIO. However, you can do just about anything using a 2 screen Listview and Add/Edit Screen Combination (a simple FM) that you can do with a grid. In future releases of ScreenIO, we will add support for Grids&lt;br /&gt;
Directly.&lt;br /&gt;
&lt;br /&gt;
===== Floating Child Windows =====&lt;br /&gt;
&lt;br /&gt;
ScreenIO runs perfectly fine in both BR 4.1 and BR 4.2. However, it does&#039;t currently support advanced BR 4.2 features such as floating child windows. This will be coming soon, however.&lt;br /&gt;
&lt;br /&gt;
=== Implementation Guide ===&lt;br /&gt;
&lt;br /&gt;
Implementing your new Screen Functions in your existing programs is simple, modular, and flexible. The same screen can be used in multiple places in your program suite. Any changes or bug fixes to your Screen Function change it everywhere that it is used, thanks to the power of Libraries.&lt;br /&gt;
&lt;br /&gt;
If you order a screen function from Sage AX, we will send you information explaining how to implement it. If you want to read about all the various ways to implement a screen, read on. If you are unsure what one of the options means, don&#039;t worry about it. If you buy a screen from Sage AX, we&#039;ll tell you which options apply to your screen.&lt;br /&gt;
&lt;br /&gt;
==== Installing your new screen ====&lt;br /&gt;
&lt;br /&gt;
When you order a screen, Sage will send you the following files:&lt;br /&gt;
&lt;br /&gt;
  data\screenio.dat     - Screen Header Data file containing your new screen and all your old screens&lt;br /&gt;
  data\screenio.key     - Screen Header Key file&lt;br /&gt;
  data\screenfld.dat    - Screen Fields Data file containing all the fields for your screens&lt;br /&gt;
  data\screenfld.key    - Screen Fields Key file&lt;br /&gt;
  data\screenfld.ky2    - Screen Fields Key file&lt;br /&gt;
 &lt;br /&gt;
  screenio.br           - Free ScreenIO Runtime Library required to run your  screens&lt;br /&gt;
  screenio\scrnname.br  - Screen helper library (compiled in a br program)&lt;br /&gt;
  screenio\scrnname.brs - Screen helper library (BR Source File, included for your convenience only.)&lt;br /&gt;
&lt;br /&gt;
&amp;quot;scrnname&amp;quot; is replaced by the name of your new screen.&lt;br /&gt;
&lt;br /&gt;
To begin using your new screens, simply copy the files into the main folder of your BR programs.&lt;br /&gt;
&lt;br /&gt;
==== Running your new screen ====&lt;br /&gt;
&lt;br /&gt;
You can now run your new screen by simply typing:&lt;br /&gt;
&lt;br /&gt;
  LOAD scrnname&lt;br /&gt;
  RUN&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Calling your screen from your existing programs ====&lt;br /&gt;
&lt;br /&gt;
However, to really get the most mileage out of your screen functions, you should implement them as library calls. This will enable you to interpret the result of the users action in the screen and act accordingly.&lt;br /&gt;
&lt;br /&gt;
To implement your new screens as library calls from within your existing programs, all you need to do is add a library statement to the ScreenIO runtime library, and call your screens.&lt;br /&gt;
&lt;br /&gt;
  01000 LIBRARY &amp;quot;screenio&amp;quot; : fnfm&lt;br /&gt;
  01200 let fnfm(&amp;quot;scrnname&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
When your program gets to line 1200, your screen is loaded and displayed, and the user is able to do anything your screen is set up for them to do. When they are done, control returns to your program at the line after 1200.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Returning Information from your screen ====&lt;br /&gt;
&lt;br /&gt;
The ScreenIO Runtime Library can return limited information about the execution of each screen. This return string is limited to 255 characters, and is generally used to return the key of the record edited/added/selected from the listview. If a Cancel option is available in your screen, and the user cancels, then the return will be blank.&lt;br /&gt;
&lt;br /&gt;
ScreenIO Returns the key of the record, by default. If you just draw a screen, and tie some fields from the file to it, writing no custom code at all, the key of the edited record will be the return value.&lt;br /&gt;
&lt;br /&gt;
However, by placing custom code in your screen, it is possible to override the default return value for your Screen Function with any kind of data you want.&lt;br /&gt;
&lt;br /&gt;
In general, if you want to use your screen to query the user for information that does not get saved in your system, then you create a screen and tie it to a temporary data file. In your calling program, you call the screen, and if the user did not cancel, you use that key to read the results from the temporary data file and interpret them, deleting the information from the file when you&#039;re done.&lt;br /&gt;
&lt;br /&gt;
However, if the amount of information you wanted to return was less then 255 bytes, it would be possible to override the return value for the screen to just return all that information in a string of data that could be interpreted by your calling program.&lt;br /&gt;
&lt;br /&gt;
=== Advanced Screen Implementation ===&lt;br /&gt;
&lt;br /&gt;
==== ScreenIO Runtime Engine Library Functions ====&lt;br /&gt;
&lt;br /&gt;
There are a few other useful functions in the ScreenIO Runtime Engine Library. They are all used to display and pass control to your screen, your screen but with a few different options:&lt;br /&gt;
&lt;br /&gt;
*fnfm(&amp;quot;scrnname&amp;quot;; key$, row, col, ParentKey$, ParentWindow, DisplayOnly,Dontredolistview,Recordval,Mat Passeddata$,Usemyf,Mat Myf$,Mat Myf,Path$,Selecting) - Displays and passes control to your screen. FnFm returns true if a record was selected/edited and false if the record was not edited. If the return value for the screen is numeric, then fnfm would return the numeric return value of the screen. If the return value is a string, calling fnfm will discard the string return value and return only 1 if the user didn&#039;t cancel, or 0 if they did.&lt;br /&gt;
&lt;br /&gt;
*fnfm$(&amp;quot;scrnname&amp;quot;; key$, row, col, ParentKey$, ParentWindow, DisplayOnly,Dontredolistview,Recordval,Mat Passeddata$,Usemyf,Mat Myf$,Mat Myf,Path$,Selecting) - Displays and passes control to your screen. FnFm$ returns the key of the record selected/edited, or blank if the user cancelled out of the screen. It is possible to override the return value in the screen by adding custom code to your screen. If the return value for a screen is numeric, then fnfm$ returns &amp;quot;str$()&amp;quot; of the numeric return value of the screen. Use &amp;quot;val()&amp;quot; to turn it back into a number if you need.&lt;br /&gt;
&lt;br /&gt;
*fnDisplayScreen(&amp;quot;scrnname&amp;quot;; key$, row, col, ParentKey$, ParentWindow,Recordval) - Deprecated, use fnfm instead, with the Display Only parameter. (This displays a screen, but does not pass control to it. This sort of functionality is very useful for advanced implementation of your screens in your programs. Oftentimes it is desirable, especially with a listview screen, to display a listview of items on the screen but not edit it yet. In that situation, you would want to continue in your main program, and wait until the user clicked on your listview Screen Function, at which point you would then call fnfm or fnfm$ for the same screen, allowing the user to use the listview later. The return value for fnDisplayScreen is the window number of the new Screen Function Window opened. When you are done displaying the Listview Screen Function and want to erase it, simply close the window number that fnDisplayScreen returned.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Within ScreenIO you may call screen functions from any existing screen function by placing the internal syntax for calling a screen directly in the click event for any button or any other event in your screen. This would be in the form [SCRNNAME(Row,Col)]Key$=&amp;quot;blah&amp;quot; : ParentKey$=&amp;quot;blahblah&amp;quot;. Row, Col, Key$, and ParentKey$ Are optional. You can also specify Record=, Selecting=, DisplayOnly=, and Path$=.&lt;br /&gt;
&lt;br /&gt;
The simplest (and most common) form is just to say [SCRNNAME]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==== ScreenIO Runtime Engine Library Function Parameters ====&lt;br /&gt;
&lt;br /&gt;
The ScreenIO Functions listed above all accept the following parameters:&lt;br /&gt;
&lt;br /&gt;
*Scrnname$ - This is the name of the screen you are trying to call. This is the only required parameter. If you are using fnCallScreen$, it is also possible to substitute the internal screenio syntax for calling screens here, which is [SCRNNAME(Row,Col)].&lt;br /&gt;
&lt;br /&gt;
*Key$ - This is the key of the current record you are editing. ScreenIO interprets this variable when it is loading and displaying your screen. If it is blank, it does not read the screen, and instead performs the screen&#039;s initialize event, the custom code (if there is any) for initializing a new record into the data file. However, if a key IS given, then instead it reads that record from the data file, performs the input, and saves the data.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&#039;&#039;&#039;&#039;Note:&#039;&#039;&#039; A Key should never be passed into a Listview screen&#039;&#039;&lt;br /&gt;
  &lt;br /&gt;
*Row, Col - These scalar parameters represent the physical location to place the top left corner of your screen. If no Row or Col is specified, then the screen opens in the middle of your BR window, resizing Window 0 if necessary to display your entire screen. If you DO give a Row and Col value, then it is your responsibility to make sure the Screen Function fits in the BR window - otherwise you will get the BR Internal Error for invalid Row and Col specification when you try to run the screen.&lt;br /&gt;
  &lt;br /&gt;
*ParentKey$ - This is an extra value you can pass into your screen function. It is ignored by the ScreenIO Runtime Engine Library, but it may be used by your custom functions. Most often it is used by the filter event of a listview, to limit the records in the Listview. (If a Listview has no filter event defined, then by default every record of the data file is displayed).&lt;br /&gt;
  &lt;br /&gt;
*ParentWindow - This optional parameter is used in conjunction with Row and Col to specify the parent window for the Screen Function. If no Parent Window is given, then window 0 is assumed to be the parent, and the new Screen Function opens on top of whatever other windows may have been on your screen before. If a Parent Window is given, then that Parent Window is used for the Row and Col position of your screen.  &lt;br /&gt;
  &lt;br /&gt;
*DisplayOnly - This optional Boolean Flag tells the ScreenIO Runtime Engine Library to display the screen and then exit without passing control to the screen. This parameter makes FnFm, FnFm$, and fnCallScreen$ work the same way that fnDisplayScreen works above. In the case of FnFM, the return value becomes the window number of the newly opened Screen Function. In the case of FnFM$ and FnCallScreen$, the return value becomes the &amp;quot;str$()&amp;quot; value of the window number of the newly opened Screen Function - use &amp;quot;val()&amp;quot; to get the actual Window Number as a numeric value.&lt;br /&gt;
&lt;br /&gt;
*DontRedoListview - This optional boolean parameter is used when running a screen from within another screen, for example in one of your custom functions. If the calling screen has a listview on it, the Listview will automatically be repopulated when you return. If you&#039;re calling a screen that doesn&#039;t change the contents of the listview then its better not to repopulate the listview, in order to make your screens run as quickly as possible. Use this boolean flag to instruct ScreenIO not to redraw the listview you&#039;re returning &#039;&#039;&#039;&#039;&#039;to&#039;&#039;&#039;&#039;&#039;. If you&#039;re implementing a screen that Sage AX made for you, we will have already set this for you.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&#039;&#039;&#039;&#039;Example:&#039;&#039;&#039; If you&#039;re in a listview screen and its calling an add/edit screen, this parameter is used on the call to the &#039;&#039;&#039;add/edit screen&#039;&#039;&#039; but it applies to the &#039;&#039;&#039;listview screen.&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*RecordVal - If you are editing a record in an Add/Edit Screen By Record instead of by Key, specify the Record here, and leave &amp;quot;Key$&amp;quot; blank.&lt;br /&gt;
&lt;br /&gt;
*Mat PassedData$ - Mat PassedData$ is an array you can use for passing Custom Information into your screens. Any of the functions inside the screen will have access to Mat PassedData$. If you&#039;re implementing a screen from Sage AX, we will tell you if there is any custom data you need to pass in.&lt;br /&gt;
&lt;br /&gt;
*UseMyF - If you set this boolean parameter to True then you can pass in your own mat F$ and mat F arrays. Instead of reading the record from the disk, ScreenIO will use the record in the arrays you&#039;re passing in. Use this for an Add/Edit screen when you don&#039;t want ScreenIO to read or write the record on disk.&lt;br /&gt;
&lt;br /&gt;
*Mat MyF$ - This is the corresponding string array containing information from a record you want to edit with a screenio screen. Use with the UseMyF parameter above.&lt;br /&gt;
&lt;br /&gt;
*Mat MyF - This is the corresponding numeric array containing information from a record you want to edit with a screenio screen. Use with the UseMyF parameter above.&lt;br /&gt;
&lt;br /&gt;
*Path$ - This is the FileIO Path$ Parameter that specifies a Data Path to be prepended to the path specified in your file layouts, in order to accommodate situations where the same data file with the same layout occurs in multiple paths.&lt;br /&gt;
&lt;br /&gt;
*Selecting - This is a flag you can use to signal to your screens when you&#039;re running them as to the intentions of your users. You can use it to define different &amp;quot;modes&amp;quot; for the current screen. The parameter is not used by ScreenIO at all, but simply passed onto your functions, similar to the way ParentKey$ works.&lt;br /&gt;
&lt;br /&gt;
=== How does it work Internally ===&lt;br /&gt;
&lt;br /&gt;
==== Program Flow ====&lt;br /&gt;
&lt;br /&gt;
When you call your new screen, no matter how it is called, the screen layout is loaded from the screenio data files (ScreenIO.DAT and ScreenFld.DAT). Then, if a file layout is given, the file is opened, and if there is a key given, then the key is read and the read event is triggered. If a key is not given, then the initialize event is triggered.&lt;br /&gt;
&lt;br /&gt;
After that ScreenIO maps the fields in the data file onto the fields on your screen and displays them, allowing the user to interact with the screen as they wish. The screen remains in control until &amp;quot;[[#ExitMode|ExitMode]]&amp;quot; is triggered, either from one of the events, or by pressing the ESC key to trigger an [[#ExitMode|ExitMode]] of Cancel (by default), or the ENTER key to trigger an [[#ExitMode|ExitMode]] of Select (by Default).&lt;br /&gt;
&lt;br /&gt;
Once a Screen Function Event has been triggered that sets [[#ExitMode|ExitMode]] to one of the various valid exit modes, the screen is exited, and depending on [[#ExitMode|ExitMode]], the return value is calculated and the data is saved or added, or dropped, or ignored, and the return value is set. The Prewrite Event and the Exit event is triggered here.&lt;br /&gt;
&lt;br /&gt;
==== Philosophy ====&lt;br /&gt;
&lt;br /&gt;
ScreenIO is a modular event driven system for BR. The ScreenIO Design and Runtime Libraries do for BR what Visual Basic did for the Microsoft world of programming. However, its easier to create and use ScreenIO screens then it is to write VB programs, because BR is simpler then VB in many of its internal working details, and because ScreenIO screens have the ability to write to your data files without having a stitch of custom code.&lt;br /&gt;
&lt;br /&gt;
ScreenIO was designed to eliminate the BR headache of working with 2D object-style controls in the non-object oriented world of BR programming.&lt;br /&gt;
&lt;br /&gt;
ScreenIO cannot make every program in the world. I would be very impressed if I saw someone make a video game in ScreenIO. It is limited to interfaces that BR can produce, and that means that you can only input from one screen at a time (because BR&#039;s input statement is Modal). It can only make BR style listviews and grids, and your interfaces work using rows and columns, instead of twips or pixels like other languages.&lt;br /&gt;
&lt;br /&gt;
Instead, ScreenIO&#039;s focus is on remaining as simple as possible, while still allowing the flexibility to accomplish 90% of the business programming purposes. It can&#039;t make absolutely everything - if it could, it would become unruly and difficult to use. By limiting the scope, however, we are able to create 90% of business programs, much faster and easier then ANY other method of programming on the market.&lt;br /&gt;
&lt;br /&gt;
==== Modular ====&lt;br /&gt;
&lt;br /&gt;
Because ScreenIO is Modular, it is extremely easy to implement your screens in any of your existing programs using the chain statement, or more commonly, a library function call. Your screens can be called from each other, even recursively should you so desire.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Event Driven ====&lt;br /&gt;
&lt;br /&gt;
Because ScreenIO is Event Driven, it is easy to call any of your existing business logic code from one of our screens.&lt;br /&gt;
&lt;br /&gt;
Each ScreenIO Screen Function has several events, that can be used to extend the functionality of your screen, provide custom validation, provide custom filtering on a Listivew, extend functionality by linking to additional screens, and control and override the return values of your Screen Functions.&lt;br /&gt;
&lt;br /&gt;
Your Screen Functions have the following events that can each be overridden with custom code, a library call, an execute command, or a link to another screen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Screen Events =====&lt;br /&gt;
&lt;br /&gt;
*Enter Event: This event is triggered when your screen is first displayed.&lt;br /&gt;
&lt;br /&gt;
*Initialize Event: This event is triggered any time you call your screen without giving it a key$ (as long as there is a data file). The initialize event is used to initialize the values for newly added records in one of your data files, in an Add/Edit Screen.&lt;br /&gt;
&lt;br /&gt;
*Read Event: This event is triggered when your screen reads the initial record, and in a Listview screen, any time the Listview selection is changed. It is primarily used for unpacking the data and placing it on a screen.&lt;br /&gt;
&lt;br /&gt;
*Write Event: This event is triggered when the user selects the &amp;quot;Save&amp;quot; option in your screen, just before actually saving the data to the disk. In the Write event, you can cancel the users exiting of the screen, or change the exit mode to any other exit mode you like. You can also make any last minute changes to the data before it is saved to the disk.&lt;br /&gt;
&lt;br /&gt;
*Mainloop Event: This event is triggered every time the main Rinput Fields statement is passed. You can use this event to update information on the screen, implement special keys, or implement windows menu&#039;s in your screenio screens.&lt;br /&gt;
&lt;br /&gt;
*Wait Event: This event works in conjunction with the timeout setting you specify for your screen. This timeout value specifies the number of seconds before triggering a WAIT event. If you specify a WAIT event here, your event will be triggered if the keyboard is idle for that many seconds. If you do not write a WAIT event, the default ScreenIO Wait event is triggered.&lt;br /&gt;
&lt;br /&gt;
*Record Locked: This event is triggered whenever a record is locked in a screenio screen. If you do not specify your own locked record event, the default ScreenIO Locked Record Event is triggered.&lt;br /&gt;
&lt;br /&gt;
*Exit Event: This event is triggered last, when the screen is being closed.&lt;br /&gt;
&lt;br /&gt;
===== Individual Control Events =====&lt;br /&gt;
&lt;br /&gt;
Each of the controls on your screen has its own event, which get triggered in various ways depending on the control.&lt;br /&gt;
&lt;br /&gt;
*Filter Event - In a Listview Control, the listviews event is the filter function that gets called to determine if the currently selected record should be added to the listview or not. Your filter function receives MAT F$ and MAT F for the screen, and if it returns true, (anything other then 0 or blank) then the record is included in the listview. If your filter function returns an HTML color code, then that HTML color is used to color that specific row of the listview. If there is no filter function, the listview displays every record in the data file.&lt;br /&gt;
**Listviews&lt;br /&gt;
  &lt;br /&gt;
*Validation - In a data Control, the data Control&#039;s event is the validation function that gets called to determine if the data is acceptable or not. If there is no Validation Function, then the data gets saved according to internal rules: All text data gets saved regardless of what it is, and numeric data is saved only if the user entered valid numeric data. The validation function receives the value the user is trying to save, and it can modify that data, and return true or false, to force the data to be saved or not. (However, you never can force saving string data in a numeric field, that will always be discarded by the ScreenIO Runtime Engine).&lt;br /&gt;
**CheckBoxes&lt;br /&gt;
**SearchBoxes&lt;br /&gt;
**Radio Buttons&lt;br /&gt;
  &lt;br /&gt;
*Click Events - Non-Data Controls have a &amp;quot;Click&amp;quot; event. This event is triggered whenever the user clicks on the control.&lt;br /&gt;
**Buttons&lt;br /&gt;
**Pictures&lt;br /&gt;
**Captions&lt;br /&gt;
&lt;br /&gt;
===== Purpose of Events =====&lt;br /&gt;
&lt;br /&gt;
By overriding various events with custom code, we can make your screen functions behave any way you want them to.&lt;br /&gt;
&lt;br /&gt;
=== Screens with two data files ===&lt;br /&gt;
&lt;br /&gt;
ScreenIO Screen Functions are limited to one data file each. This means that each ScreenIO Screen function can only directly and automatically modify the MAIN data file for the screen. However, it is possible to modify additional related data files through the custom code added to the various screen events.&lt;br /&gt;
&lt;br /&gt;
It is possible to use ScreenIO to modify data sets of two data files with a parent/child relationship, by using four screens and tying them together, and setting special code in various events.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Example ====&lt;br /&gt;
&lt;br /&gt;
If you had a set of invoice files, with one invoice header file and another invoice detail file containing the line items of various invoices, and you wanted to maintain those files with ScreenIO, you would create four screens.&lt;br /&gt;
&lt;br /&gt;
The first screen would be a listview screen tied to the invoice header that would list all the invoices on record. (You could also set up a filter function limiting this display to invoices for a certain customer (passed in using ParentKey$) if you desired.) This screen would have buttons linking to the Add/Edit screen for invoice headers (the second screen described below).&lt;br /&gt;
&lt;br /&gt;
The second screen would be the Edit screen for the listview header. This screen would link (using Display Only) to the third screen (below) in its Enter Event. It would also have a button linking to the third screen (below) without the Display Only option, so that the user can click on this button and jump to the Listview displaying line items for the invoice.&lt;br /&gt;
&lt;br /&gt;
The third screen would be a listview for the invoice detail lines. This screen would have to have a filter function to limit its display to only lines on the currently selected invoice (which would be passed in using ParentKey$). You would link to this screen using &amp;quot;DisplayOnly&amp;quot; in the second screens &amp;quot;Enter Event&amp;quot;, so that when they are editing the invoice header records, they will also be able to view the line items on the listview. You would also have placed a button on Screen 2 linking to Screen 3 without Display Only (described above). The third screen, just like the first screen above, would have buttons linking to the Add/Edit screen for Invoice Detail items.&lt;br /&gt;
&lt;br /&gt;
The fourth screen would be a simple Add/Edit screen for the detail line items. In the initialize event for this screen, you would want to initialize the value in the detail file that ties it to the header file. In our example of invoices, we would initialize an invoice line item by specifying which invoice it appears on.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
This process allows you to quickly and easily create a set of four Screen Functions that preform complete FM operations on two linked data files with a parent/child relationship.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The ScreenIO Animated Loading Icon ===&lt;br /&gt;
ScreenIO comes with an Animated Loading Icon that automatically appears whenever a listview takes a long time to load. This tells the user that something is happening, so they know its not just hung.&lt;br /&gt;
&lt;br /&gt;
You don&#039;t have to do anything to your screens to use the loading animation. It automatically happens whenever a listview takes more then a couple seconds to load.&lt;br /&gt;
&lt;br /&gt;
==== Changing the Loading Icon ====&lt;br /&gt;
See [[#Working_with_the_ScreenIO_Loading_Icon|Working with the ScreenIO Loading Icon]] for more information.&lt;br /&gt;
&lt;br /&gt;
=== Save Money with Screen Functions ===&lt;br /&gt;
&lt;br /&gt;
==== Lower Development Costs ====&lt;br /&gt;
&lt;br /&gt;
A &amp;quot;Screen Function&amp;quot;, depending on the complexity, represents about 4 - 8 hrs of traditional development time. Sage AX is selling all custom screens at a base price of $150. Custom processing code is occationally necessary to achieve particularly powerful effects, and it is available at a small additional charge. Most screen functions require little or no custom code, but more complex functionality is available. You can do just about anything with a screen.&lt;br /&gt;
&lt;br /&gt;
Because the screens are contained in Data files, they are easy to modify and easy to maintain.&lt;br /&gt;
&lt;br /&gt;
Because ScreenIO does the bulk of the work for you, the cost for custom processing code in your screens is lower then you might think.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Lower Maintenance Costs ====&lt;br /&gt;
&lt;br /&gt;
The ScreenIO Runtime Library required to run your screens is free.&lt;br /&gt;
&lt;br /&gt;
The ScreenIO Design engine used to create your screens is available for sale, for a one time unlimited-lisence fee. It will pay for itself after about 30 screens.&lt;br /&gt;
&lt;br /&gt;
You don&#039;t need any special editor to edit the custom code that&#039;s already in your screen. That can be done by simply loading the screen helper library and modifying the code, the same way you would modify any BR program. However, if you make those sorts of changes yourself, you should send us a copy of your changes so that they can be included in any future modifications we make to that screen for you.&lt;br /&gt;
&lt;br /&gt;
Because ScreenIO uses FileIO to access all your data files, you never need to update your screens for file layout changes. This happens automatically because of the magic of the [[FileIO Library]]. The only thing you have to do is update your File Layouts.&lt;br /&gt;
&lt;br /&gt;
==== Estimated Price for your Screen Project ====&lt;br /&gt;
&lt;br /&gt;
Please contact Sage AX (gabriel.bakker@gmail.com) with your project details to recieve a free price quote.&lt;br /&gt;
&lt;br /&gt;
Visit http://www.sageax.com/products/screenio-library/ for more details.&lt;br /&gt;
&lt;br /&gt;
== Making ScreenIO Screens ==&lt;br /&gt;
&lt;br /&gt;
It is also possible to purchase a ScreenIO Designer License, that entitles you to a full copy of the ScreenIO Designer, which you can use to make your own ScreenIO Screens. This part of the documentation deals with using the ScreenIO Screen Designer.&lt;br /&gt;
&lt;br /&gt;
=== The ScreenIO Designer (Overview and Reference) ===&lt;br /&gt;
[[image:Designer_-_Add_Edit_Screen_-_Field_Selection_Mode.jpg|thumb|800px]]&lt;br /&gt;
&lt;br /&gt;
The ScreenIO Designer is modeled after other modern visual program designers. However, it is written entirely in BR, and as such has a few limitations. We have done our best to work past the limitations of traditional BR programming by employing a clever combination of tricks and advanced BR syntax.&lt;br /&gt;
&lt;br /&gt;
At the top of the screen is the traditional Windows Menu. The left column of the Screen is made up of the Toolbar, which contains the Window Attributes, the Field List, and the ToolBox. At the bottom of the screen is the Debug window. The remaining space is the Editor window, where you can view and modify your screen in a graphical programming environment.&lt;br /&gt;
==== Windows X ====&lt;br /&gt;
Clicking on the Windows X from the ScreenIO Designer will close the ScreenIO Designer and exit BR.&lt;br /&gt;
&lt;br /&gt;
Clicking on the Windows X when running your screen will Cancel and Exit out of all screens that you may currently be in recursively until you reach the calling program. It is up to your calling program to then close whatever it was doing and exit.&lt;br /&gt;
&lt;br /&gt;
If there is no calling program, then clicking on the Windows X when running a ScreenIO screen will close the program and exit BR.&lt;br /&gt;
==== ScreenIO Windows Menu ====&lt;br /&gt;
===== File =====&lt;br /&gt;
File Options&lt;br /&gt;
====== New ======&lt;br /&gt;
Create a new screen.&lt;br /&gt;
====== Load ======&lt;br /&gt;
Load a previously saved screen.&lt;br /&gt;
====== Save and Compile ======&lt;br /&gt;
Save and Compile your screen.&lt;br /&gt;
====== Compile ======&lt;br /&gt;
Compile your screen only. Use this if you&#039;ve changed some code but you haven&#039;t changed the screen itself.&lt;br /&gt;
====== Export Screen ======&lt;br /&gt;
Export your screen to a ScreenIO File (*.sio) for transferring it between different ScreenIO implementations.&lt;br /&gt;
&lt;br /&gt;
This will not save the custom screen functions. It is necessary to transfer any required custom screen functions by hand from the functions\ subfolder in your source ScreenIO implementation.&lt;br /&gt;
====== Import Screen ======&lt;br /&gt;
Import a screen from a ScreenIO File (*.sio).&lt;br /&gt;
====== Purge ScreenFlds File ======&lt;br /&gt;
Because of the way ScreenIO Stores the screen information, the screenflds file tends to grow and grow. Run this menu option to purge all deleted records from this file and free up all the unnessicary space.&lt;br /&gt;
====== Recompile All Screens ======&lt;br /&gt;
This menu option automatically recompiles all your ScreenIO Autogenerated Helper Libraries. This is useful if you made a change to a Custom Screen Function that is in use by more then one screen, and you want to apply the change everywhere in your implementation at once.&lt;br /&gt;
====== Quit ======&lt;br /&gt;
Exit the ScreenIO System to a BR Prompt.&lt;br /&gt;
&lt;br /&gt;
If you want to exit BR entirely from just one click, click on the windows &amp;quot;X&amp;quot;.&lt;br /&gt;
===== Options =====&lt;br /&gt;
Performance Options&lt;br /&gt;
====== Click to Move ======&lt;br /&gt;
Default: On&lt;br /&gt;
&lt;br /&gt;
This setting enables/disables the grid of blue dots that allows you to quickly move your controls around the screen by just clicking on the destination. On some computers, or some network settings, the click-to-move dots can slow down performance noticably. If this happens, disable the dots by using this menu setting, and move the controls around using the keyboard instead of the click to move dots. (Use the Arrow Keys).&lt;br /&gt;
&lt;br /&gt;
The Click to Move dots are particularly slow when you are modifying large 2D controls such as ListViews.&lt;br /&gt;
&lt;br /&gt;
====== Preview Listviews ======&lt;br /&gt;
Default: On&lt;br /&gt;
&lt;br /&gt;
ScreenIO attempts to provide the developer with a WYSIWYG environment. To that end, it renders your screen as much as it possibly can at design time.&lt;br /&gt;
&lt;br /&gt;
If you make a Listview Screen for a Data File that has records in it, the ScreenIO Designer will do the best it can to populate that listview even while you are designing the listview.&lt;br /&gt;
&lt;br /&gt;
Previewing the listviews can be very slow for large data files. If you wish to increase performance, turn the &amp;quot;Preview Listviews&amp;quot; setting off.&lt;br /&gt;
====== Real Time Filters ======&lt;br /&gt;
Default: Off&lt;br /&gt;
&lt;br /&gt;
If your ScreenIO listview has a custom filter function assigned to it, you can enable the use of the filter function during the WYSIWYG Preview Listview rendering.&lt;br /&gt;
&lt;br /&gt;
Depending on the resources of your computer, this setting can have a serious impact on performance.&lt;br /&gt;
&lt;br /&gt;
If the Preview Listviews setting is turned off, then the Real Time Filters setting has no effect.&lt;br /&gt;
&lt;br /&gt;
===== Add Control =====&lt;br /&gt;
The add control menu gives you keyboard access for adding any control you want to your screen. &lt;br /&gt;
&lt;br /&gt;
====== Add Field ======&lt;br /&gt;
This places the cursor in the Fields Listview where you can select fields from your data file and with the arrows and add them to your screen by pressing &amp;quot;Enter&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
====== Add Exit Buttons ======&lt;br /&gt;
This automatically adds Exit buttons to your screen. If its a listview screen, then it adds &amp;quot;Select&amp;quot; and &amp;quot;Cancel&amp;quot; buttons. If its an Add/Edit screen, then it gives you &amp;quot;Save&amp;quot; and &amp;quot;Cancel&amp;quot; buttons. These buttons are added to the bottom right corner of your screen, lining up with your rightmost controls. &lt;br /&gt;
&lt;br /&gt;
====== Add Textbox ======&lt;br /&gt;
Adds a Textbox. This is the same as clicking the button in your Toolbox.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====== Add Caption ======&lt;br /&gt;
Adds a Caption. This is the same as clicking the button in your Toolbox.&lt;br /&gt;
====== Add Checkbox ======&lt;br /&gt;
Adds a Checkbox or a Radio Button. This is the same as clicking the button in your Toolbox.&lt;br /&gt;
====== Add Listview ======&lt;br /&gt;
Adds a Listview to your screen. This is the same as clicking the button in your Toolbox.&lt;br /&gt;
====== Add Searchbox ======&lt;br /&gt;
Adds a SearchBox to your screen. This is the same as clicking the button in your Toolbox.&lt;br /&gt;
====== Add Button ======&lt;br /&gt;
Adds a Button. This is the same as clicking the button in your Toolbox.&lt;br /&gt;
====== Add Picture ======&lt;br /&gt;
Adds a Picture. This is the same as clicking the button in your Toolbox.&lt;br /&gt;
====== Skip A Space ======&lt;br /&gt;
Skips a space for the automatic placement of controls. This is the same as clicking the button in your Toolbox.&lt;br /&gt;
&lt;br /&gt;
===== Screen =====&lt;br /&gt;
Screen Options&lt;br /&gt;
====== Adjust Screen Size ======&lt;br /&gt;
Automatically resizes your screen to just large enough to fit all your controls on it.&lt;br /&gt;
====== Move Controls ======&lt;br /&gt;
This puts ScreenIO into Control Movement Mode&lt;br /&gt;
====== Visit Checklist ======&lt;br /&gt;
This puts the curser in the Debug listview. You can do the same thing by clicking on the Debug Listview.&lt;br /&gt;
====== Set FG Color ======&lt;br /&gt;
This brings up the color selector, allowing you to select the Foreground Color for your screen. This is the same as clicking on the button in the Window Attributes panel.&lt;br /&gt;
====== Set BG Color ======&lt;br /&gt;
This brings up the color selector, allowing you to select the Background Color for your screen. This is the same as clicking on the button in the Window Attributes panel.&lt;br /&gt;
====== Select File Layout ======&lt;br /&gt;
This brings up the file selection dialog. This is the same as clicking on the button in the Window Attributes panel.&lt;br /&gt;
====== Set Events ======&lt;br /&gt;
This menu option does the same thing that clicking on the &amp;quot;Set Events&amp;quot; button (under Window Attributes) does: It opens a window where you can specify your Screen level Event Handler Custom Screen Functions.&lt;br /&gt;
====== Set Tab Order ======&lt;br /&gt;
This menu option allows you to set the tab order by clicking on all of your screen controls in the order that you want the tab order to go. This function is also availble from the &amp;quot;Set Tab Order&amp;quot; button in the Window Attributes corner of the ScreenIO Designer.&lt;br /&gt;
====== Configure Debug ======&lt;br /&gt;
This option allows you to specify any special instructions to use when testing the screen via the Test Screen menu option below.&lt;br /&gt;
====== Test Screen ======&lt;br /&gt;
This option fires up a second copy of BR to test your screen. All screenIO screens can be exited by clicking on the Windows X. Your screen runs in a completely separate instance of BR, so you don&#039;t have to worry about the test of the screen screwing up whats going on in your editor.&lt;br /&gt;
&lt;br /&gt;
Its important to remember to save your screen before testing it. Otherwise, you will see the previous version of the screen when you test it.&lt;br /&gt;
&lt;br /&gt;
ScreenIO will attempt to use the same BR executable and brconfig.sys file that you loaded screenio with, so make sure its the one you want to use for your application.&lt;br /&gt;
&lt;br /&gt;
===== Help =====&lt;br /&gt;
Help Menu&lt;br /&gt;
====== Documentation ======&lt;br /&gt;
This menu option links to this wiki document.&lt;br /&gt;
====== About ======&lt;br /&gt;
Opens the ScreenIO About screen.&lt;br /&gt;
&lt;br /&gt;
==== ScreenIO Designer Modes ====&lt;br /&gt;
The ScreenIO Designer has several different modes that it operates in. For the most part this is designed to be seamless to the programmer but it may help to understand whats going on behind the scenes.&lt;br /&gt;
&lt;br /&gt;
BR has a major interface limitation, in that only one child window is able to be input from at a given time. The ScreenIO designer attempts to hide this problem by using different modes. The modes are as follows:&lt;br /&gt;
&lt;br /&gt;
  let Inputattributesmode=1&lt;br /&gt;
  let Inputfieldlistmode=2&lt;br /&gt;
  let Inputeditormode=3&lt;br /&gt;
  let Inputeditormovemode=4&lt;br /&gt;
  let Inputdebugmode=5&lt;br /&gt;
  let Quitmode=6&lt;br /&gt;
  let Selectcolormode=7&lt;br /&gt;
  let Selectfilelaymode=8&lt;br /&gt;
  let Inputlistviewmode=9&lt;br /&gt;
  let Selecteventsmode=10&lt;br /&gt;
  let Settabordermode=11&lt;br /&gt;
  let Configuredebugmode=12&lt;br /&gt;
&lt;br /&gt;
Input Attributes Mode is when the cursor is in the upper left corner of the screen, inputting the attributes for the whole screen. If you&#039;re in a different mode and you click on the Window Attributes, then the mode is changed to Window Attributes mode.&lt;br /&gt;
Input FieldsList Mode is when the cursor is in the fields listview, and you&#039;re selecting fields to add to the screen.&lt;br /&gt;
Input Editor Mode is when the cursor is in the attributes for a single field.&lt;br /&gt;
Input Editor Move Mode is when the cursor is in the mode where you move controls, the mode with the blue dots.&lt;br /&gt;
Input Debug Mode is when the Todo List debug at the bottom of the screen is active.&lt;br /&gt;
Quit Mode is used to tell the designer to exit.&lt;br /&gt;
Select Color Mode is the current mode whenever you&#039;re selecting a color for something.&lt;br /&gt;
Select FileLay Mode is used to select the file layout for your screen.&lt;br /&gt;
Input Listview Mode is the mode for entering the information for listview columns.&lt;br /&gt;
Select Events mode is the mode you&#039;re in when you&#039;re selecting screen level events.&lt;br /&gt;
Set Tab Order Mode is the mode for setting the tab order.&lt;br /&gt;
Configure Debug Mode is the mode for configuring the debug window.&lt;br /&gt;
&lt;br /&gt;
You can generally tell what mode you&#039;re in because that part of the screen will light up yellow.&lt;br /&gt;
==== Toolbar ====&lt;br /&gt;
The Toolbar Window is along the left side of the screen. It is made up of the Window Attributes window, the Fields List, and the Toolbox.&lt;br /&gt;
===== Window Attributes =====&lt;br /&gt;
The Window Attributes window contains information about all Screen level Attributes.&lt;br /&gt;
====== Window Name ======&lt;br /&gt;
This is the unique 8 digit Window Name. It is used as the unique key in the ScreenIO data file. It is the name you use to load your screen from code, and the name you use when you load your screen from the ScreenIO Designer File-&amp;gt;Load menu.&lt;br /&gt;
====== Caption ======&lt;br /&gt;
This is the Caption in the Windows Title Bar when you run your application. If the Window you are creating has a border specified, then this is also the caption that appears in the border of that Child Window&lt;br /&gt;
====== Rows ======&lt;br /&gt;
The number of Rows your window takes up. You can change this any time, and your screen will adjust on the fly. This makes it easy to design your screens and then adjust the size of them when you already know what they will look like.&lt;br /&gt;
&lt;br /&gt;
If you make your screen too small and not all the controls fit on it, the ones that are outside the border of the window will not be rendered, and a Debug Message will appear in the Debug Window. Simply make your screen large enough for all the controls to appear and move the offending controls away from the edge, and then resize your screen again to the size you want it to be.&lt;br /&gt;
====== Cols ======&lt;br /&gt;
The number of Columns your window takes up. See Rows (above) for more information.&lt;br /&gt;
====== Attributes ======&lt;br /&gt;
This Attributes Screen is used when opening your window. You can place any valid BR Window Attribute statement here. For example, to make your screen have a border around it, type &amp;quot;BORDER=S&amp;quot; in the Attributes setting for the window.&lt;br /&gt;
====== Picture ======&lt;br /&gt;
Type the path and filename of a picture file, and it will be used as the background image for your Screen.&lt;br /&gt;
====== Read Key ======&lt;br /&gt;
Specify the key to use when reading the file. The default is the first key specified in the layout for Add/Edit screens, and Sequential Read for Listview Screens.&lt;br /&gt;
====== Return Key ======&lt;br /&gt;
Specify the key to use when calculating the return value. The default is the first key specified in the layout.&lt;br /&gt;
====== Input Attr ======&lt;br /&gt;
Specify the Input Attr spec to use in the main Rinput Fields statement. This controls the appearance of the currently active field.&lt;br /&gt;
====== Wait Time ======&lt;br /&gt;
Specify the time to wait in seconds of keyboard inactivity before triggering a WAIT event. If you have no WAIT event specified, then ScreenIO will trigger the default ScreenIO WAIT event.&lt;br /&gt;
====== FG Color ======&lt;br /&gt;
This is the default Foreground Color when adding new controls to the screen.&lt;br /&gt;
====== BG Color ======&lt;br /&gt;
This is the background color for the screen.&lt;br /&gt;
====== File Layout ======&lt;br /&gt;
Click this button to select the file layout that your screen applies to.&lt;br /&gt;
====== Set Form Events ======&lt;br /&gt;
This button is a shortcut to the Windows Menu: Screen-&amp;gt;Set Form Events. It opens a window where you can view and configure the ScreenIO Custom Helper Functions that get triggered for each of your Form (Screen) level Events.&lt;br /&gt;
====== Set Tab Order ======&lt;br /&gt;
This button is a shortcut to the Windows Menu: Screen-&amp;gt;Set Tab Order. It allows you to change the tab order of your screen by clicking on your screen controls in the order that you would like the tab order to become.&lt;br /&gt;
===== Field List =====&lt;br /&gt;
This listview shows all the fields in the currently selected File Layout.&lt;br /&gt;
&lt;br /&gt;
Because of a limitation in BR, only one child window can be active at any given time. You can tell if you are in &amp;quot;Input Fields List Mode&amp;quot; because the background for the Listview will turn Yellow. When you are in &amp;quot;Input Fields List Mode,&amp;quot; you can navigate the listview with the mouse or arrow keys. Pressing Enter or Double Clicking on an item will add it to your new screen.&lt;br /&gt;
===== Toolbox =====&lt;br /&gt;
The toolbox contains buttons for adding each of the different control types supported by ScreenIO.&lt;br /&gt;
====== Add Field ======&lt;br /&gt;
This button adds the currently selected field from the Fields List to your new screen. This is the same as double clicking on a listview item or pressing enter while in Input Fields List Mode (while the Fields List is yellow). If you are not currently selecting a field from the Fields Listview, then clicking on this button does nothing.&lt;br /&gt;
&lt;br /&gt;
The currently selected field is added as a Textbox that is automatically tied back to your data file. To the left of this new textbox is a caption containing the description from the File Layout for this field. Both can be customized to your hearts content, and positioned any place you want on the screen.&lt;br /&gt;
====== Add TextBox ======&lt;br /&gt;
This button adds an empty Textbox Control to your new screen. This textbox control can then be configured and tied to a field from the data file, or left as a Screen field that can be accessed and modified by your custom ScreenIO Helper Functions.&lt;br /&gt;
====== MultiLine Textbox ======&lt;br /&gt;
BR Supports Multi-Line Textboxes via a little-known programming trick that dates back to the days before graphical controls. It is possible to use this technique to make multiline textboxes in BR, and ScreenIO makes the process easy for you. The only down side to BR multi-line text boxes is that you can only make a multiline text box that goes all the way to both the left and right side of the window.&lt;br /&gt;
&lt;br /&gt;
To make a MultiLine textbox in ScreenIO, simply add a regular textbox to the screen and then press the PgDn key while in movement mode. It will stretch horizontally to fill the screen, and grow to become a multiline textbox.&lt;br /&gt;
====== Add Caption ======&lt;br /&gt;
This button adds an empty Caption Control to your new screen. This caption can be configured and the Text to display can be specified. Or, you can tie it to a field in the data file, or leave it as a Screen field that can be accessed and modified by your Custom ScreenIO Helper Functions&lt;br /&gt;
====== Add CheckBox ======&lt;br /&gt;
This button adds an empty Checkbox Control to your new screen. This Checkbox can be configured and its caption can be specified. It can also be tied to a data file, or left as a Screen field that you can access and modify.&lt;br /&gt;
&lt;br /&gt;
You can tie your checkbox to a field in your data file by specifying a TrueValue and a FalseValue in addition to a FieldName for a field from the file. If the checkbox is checked, the truevalue you specify will be saved in the file. If its not, the falsevalue will be saved in the file.&lt;br /&gt;
&lt;br /&gt;
====== Add Radio Button ======&lt;br /&gt;
To add a Radio Button, start by adding a Checkbox to your screen. Then convert the Check box into a Radio Button using the following procedure.&lt;br /&gt;
&lt;br /&gt;
You can turn your checkboxes into radio buttons very easily. Simply add a group number (1,2,3,etc) in the attribute field and your checkbox will be converted to a radio button as ScreenIO builds the screen.&lt;br /&gt;
&lt;br /&gt;
You oftentimes will want to tie a group of Radio Buttons to a single field in the data file. In that event, specify the same field name for every radio button, and specify the True Value that you want associated with each Radio button in the group. For falsehood values for all the controls in the group, specify a value of &amp;quot;~ignore~&amp;quot;. This will instruct ScreenIO to ignore the falsevalue, saving the truevalue from the currently selected radio button.&lt;br /&gt;
&lt;br /&gt;
====== Add Listview ======&lt;br /&gt;
This button adds an empty listview to your new screen. This Listview can then be configured and modified. If you enter &amp;quot;Edit Listview Columns&amp;quot; mode, then you can add or remove columns from the listview. If you are currently in Edit Listview Columns mode, then you can click on the Fields List to automatically add listview columns from your datafile directly.&lt;br /&gt;
====== Add Search Box ======&lt;br /&gt;
This button adds a Search Box and ties it automatically to a listview if one is found. You can also tie the Search Box to a Listview later from its control attributes window.&lt;br /&gt;
====== Add Button ======&lt;br /&gt;
This button adds a Button to your new screen. You can specify a Click Event Handler, some custom BR code that gets triggered whenever the button is clicked on.&lt;br /&gt;
====== Add Picture ======&lt;br /&gt;
This button adds a Picture object to your new screen. Pictures, like buttons, also have a click event.&lt;br /&gt;
====== Skip a Space ======&lt;br /&gt;
This instructs ScreenIO to skip a row for the automatic placement of Screen Controls.&lt;br /&gt;
&lt;br /&gt;
==== Editor ====&lt;br /&gt;
The Editor Window contains your new screen.&lt;br /&gt;
&lt;br /&gt;
From the Editor Window you can move your Screen Controls around, and also edit each of their attributes and event functions.&lt;br /&gt;
==== Debug ====&lt;br /&gt;
The Debug window lists potential warnings and errors discovered by our Screen validation routine.&lt;br /&gt;
&lt;br /&gt;
Messages in Blue are Warnings. They point to things that our ScreenIO Validation routine believes don&#039;t really make sense, even though they aren&#039;t really going to cause an error.&lt;br /&gt;
&lt;br /&gt;
Messages in Red are Errors. If those problems are not corrected, your screen will not function properly.&lt;br /&gt;
&lt;br /&gt;
If you double click on a message, the ScreenIO validation routines will do their best to take you to the location of the error so you can find it and fix it more easily.&lt;br /&gt;
&lt;br /&gt;
=== Using the ScreenIO Designer ===&lt;br /&gt;
Now that we have gone over the various elements that make up the ScreenIO Design Library, lets take a closer look at the process of making a Screen.&lt;br /&gt;
&lt;br /&gt;
==== Create a New Screen ====&lt;br /&gt;
The first thing that every screen needs is a Screen Name.&lt;br /&gt;
&lt;br /&gt;
Fire up the ScreenIO Designer. You will notice a few messages in the Debug window, right off the bat. One of these is an error message, that says &amp;quot;Window Name cannot be blank.&amp;quot; (The message may appear white on a blue background instead of Red on a White background. This is because of the current row selection bar, which is White on Blue.)&lt;br /&gt;
&lt;br /&gt;
The Window Name is the primary unique key for the ScreenIO Screens file, and every screen needs one. You use the Screen Name when invoking your screen, and when loading it from the File-&amp;gt;Load menu.&lt;br /&gt;
&lt;br /&gt;
Enter a name for your new screen.&lt;br /&gt;
&lt;br /&gt;
The next step is to Select the File Layout for your screen.&lt;br /&gt;
&lt;br /&gt;
One of the nicest features of ScreenIO enabling truly Rapid Application Development, is ScreenIO&#039;s ability to automatically modify data files that have been defined within the [[FileIO Library]] system.&lt;br /&gt;
&lt;br /&gt;
In order to use ScreenIO to create screens that dynamically interact with your data files, it is first necessary to define your data files with FileIO style file layouts. If you have not done so, do so now. For more information on the [[FileIO Library]], visit the [[FileIO Library]]s page on this wiki.&lt;br /&gt;
&lt;br /&gt;
Click the button to the right of the text &amp;quot;File Layout:&amp;quot;. Select the file layout for the file you plan to interact with using this screen.&lt;br /&gt;
&lt;br /&gt;
[[image:Designer_-_Add_Edit_Screen_-_Field_Selection_Mode.jpg|thumb|800px]]&lt;br /&gt;
==== Add Fields to your new Screen ====&lt;br /&gt;
As soon as you select your file layout, the Field List listview should populate with all of the fields in the selected data file. At this point, you can add these fields to your Screen, by selecting them from the Field List listview and pressing the &amp;quot;Add Field&amp;quot; button (or pressing &amp;quot;Enter&amp;quot; from the Field List listview).&lt;br /&gt;
&lt;br /&gt;
The fields you add will appear in the top left corner of your screen. You can go ahead and add all the fields you want in a row. They will all go on top of each other, and the Debug Window will change to reflect that many of your controls cannot be drawn because they are on top of each other.&lt;br /&gt;
&lt;br /&gt;
If you&#039;d like to create a Listview Screen instead, you can do that by adding a Blank Listview control to your screen. Then, follow the instructions below to position your listview where you want it. When your listview is in the position and size you&#039;d like it, press Enter twice, to go to &amp;quot;Edit Listview Columns Mode&amp;quot;. Click the &amp;quot;Delete Column&amp;quot; button once to delete the Empty Listview Column that appears by default, and then click on the Field List to Jump to the Field List listview. From the field list, you can then add columns directly from your data file to your listview, by selecting them and pressing Enter.&lt;br /&gt;
&lt;br /&gt;
[[image:ScreenIO_Designer_-_Movement_Mode.jpg|thumb|800px]]&lt;br /&gt;
==== Position the fields on your new Screen ====&lt;br /&gt;
When you have finished adding your fields, click on one of your controls in the Editor window. A grid of small blue dots should appear, and your selected control will appear in Yellow, indicating that you are in Movement Mode.&lt;br /&gt;
&lt;br /&gt;
While you are in Movement Mode, ScreenIO will group your captions with your textboxes for any controls that were added together. If you move the textbox control, the caption associated with it will move automatically. This is regardless of weather or not the caption is part of a control group.&lt;br /&gt;
&lt;br /&gt;
This piece of magic is accomplished via the [[#Caption Field|Caption Field]] poperty.&lt;br /&gt;
&lt;br /&gt;
===== Keyboard Control Movement =====&lt;br /&gt;
In Movement Mode, you can position your control using the Arrow Keys. The Backspace Key makes your control narrower, while the Space Key makes your control Wider. PgUp and PgDn make your 2D control Taller or Shorter. Enter toggles between Movement Mode, and Control Attributes Mode. For more information, see the chapter on [[#Screen_Control_Movement_Mode|Screen Control Movement Mode Keyboard Reference]].&lt;br /&gt;
&lt;br /&gt;
===== Click to Move Control Movement =====&lt;br /&gt;
While BR does not support true Drag and Drop, you can approximate the functionality of Drag and Drop in BR. This is what the ScreenIO Click to Move feature is all about.&lt;br /&gt;
&lt;br /&gt;
While you are positioning your controls around the screen, the currently selected control is highlited in Yellow, and the BR Print Statement for the control is displayed in the text of the control.&lt;br /&gt;
&lt;br /&gt;
If you click on one of the blue dots, your control will jump to that location. You can use this feature to quickly place your controls on the screen.&lt;br /&gt;
&lt;br /&gt;
First, click on the control that you want to move. It will highlite in Yellow. Then click on the blue dot where you want to move it to. It will move there. If there is a control group selected, then all the controls in the selected group will be moved relative to how the main control moved.&lt;br /&gt;
&lt;br /&gt;
When you move your controls around, select the Text Box field and move that first. The Caption field will automatically move with you, following the Text Box around the screen. This may be confusing at first, but this feature is designed to save you time in the long run.&lt;br /&gt;
&lt;br /&gt;
Move all of your new controls around until your screen looks nice. You can also resize your screen at any time by changing the values in the Window Attributes window.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;However, the Click to Move feature can significantly slow down the ScreenIO Designer on computers with limited resources. If you prefer to turn it off, you can do so from the Options menu.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[image:ScreenIO_Designer_-_Control_Attributes_Window.jpg|thumb|800px]]&lt;br /&gt;
&lt;br /&gt;
==== Control Attributes Window ====&lt;br /&gt;
&lt;br /&gt;
When you have your screen looking the way you want it, it is time to begin modifying the attributes of your individual controls. Click on the control that you want to view the attributes for to select it. It will highlight in Yellow. Click it a second time (or press the Enter key) and a little window will open up showing all the attributes for the given control.&lt;br /&gt;
&lt;br /&gt;
The control attributes window shows all the customizable attributes for each of your screen objects. Each object type has its own set of attributes and events.&lt;br /&gt;
&lt;br /&gt;
[[image:ScreenIO_Designer_-_Control_Attributes_Window_-_Closeup.jpg]]&lt;br /&gt;
&lt;br /&gt;
Here is a list of all the available Control Attributes and what they do:&lt;br /&gt;
===== Control Name =====&lt;br /&gt;
This is the name for the control. Your controls do not require a name. However, if your control is not tied to a field, but you give it a name, then ScreenIO automatically reserves a place for that control in Mat S$. You can modify the value of that control within your Custom Screen Functions by using its control name.&lt;br /&gt;
&lt;br /&gt;
You can also use the control name to identify controls from within your event functions. If the control is called MyControl, then you can access its Background Color by looking at BgColor$(ctl_MyControl).&lt;br /&gt;
&lt;br /&gt;
===== Field =====&lt;br /&gt;
This is the field the control is tied to in your data file. When the user enters the screen, the record is read (or added) and the information from this field is displayed in the control. When the user finishes modifying the code and presses the Save button, the information is automatically saved back into the data file for you. Validation is provided for in the Validation Function (explained below).&lt;br /&gt;
===== Caption =====&lt;br /&gt;
This is the caption for your Caption Fields, Check Boxes, and Buttons. This is the Tool Tip Text for your Buttons (not implemented yet).&lt;br /&gt;
===== Caption Field =====&lt;br /&gt;
This is the Control Name of the field that is tied to this field for movement purposes.&lt;br /&gt;
&lt;br /&gt;
Any time you use the Movement Mode to move a control around, if it has a Caption Field specified, then the control referenced in the caption field is moved automatically for you. This helps keep the caption next to the text box it applies to.&lt;br /&gt;
&lt;br /&gt;
===== Spec Width =====&lt;br /&gt;
This is the Internal Width of the data allowed in the control. This is not to be confused with the physical display width of the control. You modify the Display Width of a control by pressing &amp;quot;Space&amp;quot; or &amp;quot;BackSpace&amp;quot; when you are in Movement Mode and the control is selected. The Spec Width specifies how wide the data in the control can be.&lt;br /&gt;
===== Sort Column =====&lt;br /&gt;
The Sort Column attribute applies to ListViews only, and specifies which column the listview is sorted on when the program is first loaded. If you are using a search box with your listview, then it is highly reccomended that you specify a Sort Column along with it. Otherwise, your Search Box will not be usable until the user manually sorts the Listview by clicking on the column headings.&lt;br /&gt;
&lt;br /&gt;
If you want your listview to sort in Descending Order, then specify a negative number. If you want it to sort in ascending order then specify a positive number here.&lt;br /&gt;
&lt;br /&gt;
For example, if you want it to sort in Descending Order on the Second Column, then specify a Sort Column of -2.&lt;br /&gt;
===== Multiselect =====&lt;br /&gt;
This check box indicates weather you want to allow multi-selection in your listview or not. If you do enable multiselection, then use mat SelectedKeys$ or mat SelectedRecords in your custom functions to see which records the user has selected from your data file.&lt;br /&gt;
===== Truth Value =====&lt;br /&gt;
The Truth Value attribute applies to Checkboxes only, and is used to translate a checked/unchecked value into the true and false values for your data files.&lt;br /&gt;
&lt;br /&gt;
Everybody uses something slightly different in their data files to represent True and False. Some people use &amp;quot;Y&amp;quot; or &amp;quot;N&amp;quot;. Some people use &amp;quot;T&amp;quot; and &amp;quot;F&amp;quot;. Some people use 1 and 0 to represent True and False in their data files. The Truth Value specifies the value that represents True in the data file for this Check Box.&lt;br /&gt;
===== Falsehood Value =====&lt;br /&gt;
The Falsehood Value attribute applies to Checkboxes only, and is used to translate a checked/unchecked value into the true and false values for your data files.&lt;br /&gt;
&lt;br /&gt;
Everybody uses something slightly different in their data files to represent True and False. Some people use &amp;quot;Y&amp;quot; or &amp;quot;N&amp;quot;. Some people use &amp;quot;T&amp;quot; and &amp;quot;F&amp;quot;. Some people use 1 and 0 to represent True and False in their data files. The Falsehood Value specifies the value that represents False in the data file for this Check Box.&lt;br /&gt;
&lt;br /&gt;
====== ~Ignore~ (Radio Buttons) ======&lt;br /&gt;
If you are using Radio Buttons, you&#039;ll often want to tie several buttons to a single data file. To do this, you will specify the value that you want each option to write to the disk using the Truth Value, and for the false value you want to specify &amp;quot;~ignore~&amp;quot;. This will tell ScreenIO to ignore the false value, and when the user selected a new radio button, the truth value for the radio button they selected will be used as opposed to the false value for the radio button that they unselected.&lt;br /&gt;
&lt;br /&gt;
===== Function =====&lt;br /&gt;
The Function attribute specifies the Click event for your Button or Picture control. Press the Edit button to select from your existing Custom Screen Functions, or create a new one. See the Custom Screen Function section of this document (below) for more information about Custom Screen Functions.&lt;br /&gt;
&lt;br /&gt;
The Click Event selects the BR Code that gets triggered whenever the user Clicks on this picture or button.&lt;br /&gt;
===== Validation =====&lt;br /&gt;
The Validation attribute identifies the Custom Screen function that gets triggered whenever the data in the control is changed. You can use this event to ensure that only valid data gets saved in the database. If your validation event returns false (0) or a null string then the data the user entered is thrown out, and the previous value is replaced in the control.&lt;br /&gt;
===== Filter =====&lt;br /&gt;
The Filter Function applies to a Listview only, and is one of the most versatile functions in the ScreenIO System.&lt;br /&gt;
&lt;br /&gt;
Your filter function gets triggered for Each Row in the data file, before it is added to the listview. You can use the Filter event to include/exclude certian records from the listview. You can also modify the data displayed in the listview before it goes to the screen.&lt;br /&gt;
===== Conversion =====&lt;br /&gt;
The conversion field specifies to ScreenIO how to treat numeric data. You can specify any valid BR field spec, or FMT, PIC or DATE here. You may also specify your own conversion function to be used when unpacking the data from the disk.&lt;br /&gt;
&lt;br /&gt;
If you use DATE then it will convert the value from a julian date into the date format you specify, and when its writing it back to the disk, it will convert it back to the julian date value before saving it to the disk.&lt;br /&gt;
===== Picture File =====&lt;br /&gt;
This specifies the path and filename of the picture file to use for the picture control. All the image types supported by BR are supported here.&lt;br /&gt;
===== Foreground Color (Header FG Color) =====&lt;br /&gt;
This is the foreground color of the control. If you intend to use Attribute Substitute statements to color your controls, then you need to leave the Foreground Color and Background Colors blank, as these values will override the colors specified in your Attribute Substitute Statements.&lt;br /&gt;
===== Background Color (Header BG Color) =====&lt;br /&gt;
This is the background color of the control. If you intend to use Attribute Substitute statements to color your controls, then you need to leave the Foreground Color and Background Colors blank, as these values will override the colors specified in your Attribute Substitute Statements.&lt;br /&gt;
===== Justification Spec =====&lt;br /&gt;
This attribute specifies the BR Justifcation Attribute to use for this screen object. The default &amp;quot;C&amp;quot; is Left Justify. You can specify:&lt;br /&gt;
&lt;br /&gt;
*C - Left Justify&lt;br /&gt;
*CC - Center Justify&lt;br /&gt;
*CR - Right Justify&lt;br /&gt;
*CU - Force Uppercase&lt;br /&gt;
*CL - Force Lowercase&lt;br /&gt;
===== Set Listview =====&lt;br /&gt;
The Set Listview attribute applies to Search Boxes only, and specifies the Listview that the Search Box is tied to. When the user types something in the Search Box, the Listview will automatically jump to the record they are typing, based on which column the listview is sorted on.&lt;br /&gt;
&lt;br /&gt;
If you have a Search Box, but no Sort column is specified in your listview, then an Error message is displayed in your Debug Window.&lt;br /&gt;
&lt;br /&gt;
When you click the &amp;quot;Set Listview&amp;quot; button, the search box is automatically tied to the listview on the screen. (At this time ScreenIO does not support more then one listview on a logical screen at a given time.) The Spec Width for the Search Box is automatically updated to match the largest column in the listview.&lt;br /&gt;
&lt;br /&gt;
If you added your listview before you added your search box, then the Search Box is already tied to your Listview by default. When your search box is tied to a listview, you will see the internal name of the listview (usually &amp;quot;LV1&amp;quot;) in the &amp;quot;Set Listview&amp;quot; button.&lt;br /&gt;
===== Attributes =====&lt;br /&gt;
The Attributes control attribute specifies the Control and Display Attributes to use when displaying the control. (Say that five times fast...)&lt;br /&gt;
&lt;br /&gt;
You can specify any valid BR attribute, including Attribute Substitution Statements from your brconfig.sys. This enables the use of BR style themes in your ScreenIO screens.&lt;br /&gt;
&lt;br /&gt;
===== Tooltip Text =====&lt;br /&gt;
Here you can specify the help text, if any, to be associated with the given control. You can specify your own helplevel if you know how to do so. If you do not specify your own help level, ScreenIO defaults to the most unused help level available in the version of BR you&#039;re running. This is level 1 for 4.1 and level 0 for 4.2 or higher, indicating to display the help text as tooltip text whenever the mouse is over the control.&lt;br /&gt;
&lt;br /&gt;
===== User Data =====&lt;br /&gt;
This is a field you can use for any purpose you like. You can view and modify this field in your screen functions.&lt;br /&gt;
&lt;br /&gt;
===== Protected =====&lt;br /&gt;
This indicates if a field is protected or not. If its protected, then it is kept automatically out of the input fields statement, keeping the user from modifying it. We do it manually because there are certian times when it doesn&#039;t work properly using the standard BR Protected attribute. However if you wish to use the Standard BR Protected Attribute, you can always specify a &amp;quot;P&amp;quot; in the Attributes field. This value, and all of these values, can be changed at runtime from any of your custom functions.&lt;br /&gt;
&lt;br /&gt;
===== Invisible =====&lt;br /&gt;
This indicates if a field is invisible or not. If it is invisible, then it is kept off the screen entirely. This is different from BR&#039;s invisible attribute, which hides the data behind a mask of &amp;quot;*&amp;quot;s. If you wish to use the standard BR invisible attribute, you can specify an &amp;quot;I&amp;quot; in your Attributes field. This value, and all of these values, can be changed at runtime from any of your custom functions.&lt;br /&gt;
&lt;br /&gt;
==== Save and Test Screen ====&lt;br /&gt;
Once you have finished adjusting the positions, appearance, and behavior of your screen controls, it is time to save your screen. Select &amp;quot;Save&amp;quot; from the File dropdown menu and your new screen is written to the disk, and its Autogenerated Screen Helper library is compiled for you.&lt;br /&gt;
&lt;br /&gt;
You may now select &amp;quot;Test Screen&amp;quot; from the Screen menu, to test your new screen in a seperate BR process.&lt;br /&gt;
&lt;br /&gt;
==== Conclusion ====&lt;br /&gt;
Your new Add/Edit screen contains everything necessary to Add and Edit records in the selected data file, and you didn&#039;t have to write any custom code at all.&lt;br /&gt;
&lt;br /&gt;
However, most screens you write will most likely utilize custom code to achieve a nicer effect. You can use your Custom Screen Functions to do just about anything with your ScreenIO Screen. For more details about Custom Screen Functions, see the Custom Screen Function section in this document (below).&lt;br /&gt;
&lt;br /&gt;
=== ScreenIO Custom Screen Functions ===&lt;br /&gt;
You can already see that the ScreenIO system is the fastest way to develop functioning software in the BR world. Simple Listview and FM screens can already be quite powerful, without writing a stitch of custom code. Because of the object oriented database foundation afforded to us by FileIO, we can achieve some pretty amazing results in just a few minutes of graphic design with a WYSIWYG editor.&lt;br /&gt;
&lt;br /&gt;
However, I&#039;m sure you can already think of hundreds of situations where the default ScreenIO behavior is insufficient to achieve the results expected of custom code.&lt;br /&gt;
&lt;br /&gt;
Its with ScreenIO Events and Custom Screen Functions, that the power of the ScreenIO Rapid Application Development system really begins to unfold.&lt;br /&gt;
&lt;br /&gt;
You can write custom events to initialize your new record, unpack a record after reading it, validate a record before saving it, and open an close your screens. You can also place code in the events for your individual controls. You can add custom code to your listview&#039;s Filter Event, or the Click events for your Buttons and Pictures, and you can have your custom code perform Validation.&lt;br /&gt;
&lt;br /&gt;
Your Custom Screen Functions can modify any value in the ScreenIO System, including the Control Attributes for your individual controls. All your screen&#039;s controls can be referred to by their FileIO syntax in the mat F$ and mat F arrays that are read from your data file. Simply read or change the data in the file record (mat f$ and mat f) and it will be reflected in real time on the screen.&lt;br /&gt;
&lt;br /&gt;
If you place controls on your screen and don&#039;t tie them to a field, but give them a control name instead, then they are placed in a special array called mat S$ and you can access and modify their data values there, by control name.&lt;br /&gt;
&lt;br /&gt;
By writing solid clean code, you can even reuse your Custom Screen functions, making future screen development faster even for complex powerful screens.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== ScreenIO Events ====&lt;br /&gt;
The screenIO system has several Events that can trigger your custom code. You will write different sorts of functions for each type of event.&lt;br /&gt;
&lt;br /&gt;
===== Form (Screen) Level Events =====&lt;br /&gt;
ScreenIO supports eight Screen level events. These are major events triggered by the state of the screen as a whole.&lt;br /&gt;
====== Enter Event ======&lt;br /&gt;
The Enter Event is triggered when your screen first loads. You can use it to initialize Screen Global Variables, Open additional data files, Initialize values on the screen, and even load other screens that you want to appear to the user as being a part of this screen.&lt;br /&gt;
====== Initialize Event ======&lt;br /&gt;
The Initialize Event is triggered from an Add/Edit screen when you are adding a new record to the data file. This happens any time you call FnFM without specifying the key to edit. (See Using Screens above). Use the Initialize Event to initialize the data in a new record that you are adding.&lt;br /&gt;
&lt;br /&gt;
It is often useful to have your Initialize Event Function call your Read Event Function.&lt;br /&gt;
====== Read Event ======&lt;br /&gt;
The Read Event is triggered upon a successful read of the data file. This happens in an Add/Edit screen any time you are loading a record to modify it.&lt;br /&gt;
&lt;br /&gt;
You most often use this event to Unpack the data from the data file for Screen Display purposes. This is why you sometimes want it to happen on Initialization of new records as well as the reading of existing records.&lt;br /&gt;
&lt;br /&gt;
On a listview screen, the Read Event behaves totally differently. On a listview screen, you never give a key when you call the screen, so the Read event never gets triggered when the screen is loading. Instead, on a listview screen, the Read Event is triggered any time the user changes which row is currently selected in your listview. You can use this to update reference information on the screen from the new record in the data file.&lt;br /&gt;
====== Mainloop Event ======&lt;br /&gt;
The mainloop event is an event thats triggered every time the main RINPUT FIELDS statement is executed when running your screenio screen. This means, every time anything happens, the mainloop event happens first. You can use the mainloop event to test for fkey 98 (the windows dropdown menu) and add dropdown menu support to your screenio screen.&lt;br /&gt;
&lt;br /&gt;
You can also place the &amp;quot;X&amp;quot; attribute in various fields to trigger the Mainloop Event to fire whenever the user moves the cursor out of these fields, in order to update the screen in some way.&lt;br /&gt;
&lt;br /&gt;
Another way to use the mainloop event is to use the config keyboard command to remap any key on the keyboard to an fkey value, and test for that fkey value, tying your own custom action to any key on the keyboard.&lt;br /&gt;
&lt;br /&gt;
See Example [[#Mainloop_Function|Mainloop Function]].&lt;br /&gt;
====== Wait Event ======&lt;br /&gt;
The WAIT event is triggered any time your screen has a WAIT value specified in the Window Attributes panel. This event determines the action you would like ScreenIO to take when the keyboard has been idle for some time.&lt;br /&gt;
&lt;br /&gt;
Your WAIT event return value determines the action screenio takes after the main processing of your WAIT event. If your WAIT event function returns True, then ScreenIO clears the WAIT condition and continues executing the screen until another event is triggered. If your WAIT event function returns False, then the ScreenIO screen is closed with an [[#ExitMode|ExitMode]] of Cancel, and the screen is backed out of.&lt;br /&gt;
&lt;br /&gt;
If you do not specify a WAIT event function, then the default ScreenIO WAIT event code fires, and ScreenIO informs the user that their keyboard has been idle for some time, and requests that they please press a key sometime in the next 30 seconds or else they will be logged out of the current screen. If they press a key in the alotted time, they are taken back to the RINPUT FIELDS statement and allowed to continue using the screen. If not, the screen closes and logs them out, freeing up the record so someone else can use it.&lt;br /&gt;
&lt;br /&gt;
====== Locked Record Event ======&lt;br /&gt;
The Locked Record event is triggered any time ScreenIO attempts to read a record that has been locked by another user. Your Locked Record event should tell ScreenIO what to do when a record locking error occurs in your screen.&lt;br /&gt;
&lt;br /&gt;
If your Locked Record event returns True, then the read is attempted again. If it returns false, then the read is cancelled and the screen is exited.&lt;br /&gt;
&lt;br /&gt;
If you do not specify a Locked Record event function, then the default ScreenIO Locked Record event code fires. The user is informed of a file sharing violation and the user name of the person who has the record locked. They are given the option to Retry or Cancel the operation. If they select Retry, the read is attempted again. if they select false, then the read is cancelled and the screen is exited.&lt;br /&gt;
====== Write Event ======&lt;br /&gt;
The Write Event happens just before your screen exits, when Save has been selected. You can use the Write event to perform last minute validation. From the Write Event, you can correct any validation problems, discard the invalid data, or cancel the [[#ExitMode|ExitMode]], forcing ScreenIO to continue to process and forcing the user to fix the error before continuing.&lt;br /&gt;
&lt;br /&gt;
====== Exit Event ======&lt;br /&gt;
The Exit Event happens when the screen exits. If you had to open reference data files in your screens &amp;quot;Enter&amp;quot; event, then the &amp;quot;Exit&amp;quot; event is a good place to close those same data files.&lt;br /&gt;
===== Control Specific Events =====&lt;br /&gt;
In addition to the Form Level events, ScreenIO provides one custom event per control. The meaning of this event is different depending on the control type. Some controls don&#039;t have any event at all.&lt;br /&gt;
====== Click Event ======&lt;br /&gt;
The Click Event is the simplest event to code for. It is triggered whenever someone clicks on a Button or a Picture. In this event, you can place any code that you want to be called when they click on the button.&lt;br /&gt;
&lt;br /&gt;
See Example [[#Click_Event_Function|Click Event Function]].&lt;br /&gt;
====== Validate Event ======&lt;br /&gt;
The Validate Event is triggered whenever the data in the element changes. You can use this event to discard or accept the data, display a msgbox to the user, and position the curser. If your validation routine returns non-zero and non-blank, then the value the user typed is accepted and saved. If your validation routine returns null or 0 then the value the user typed in is ignored and the previous value is retained. You can also modify the value directly by modifying the optional parameter &amp;quot;FieldText$&amp;quot; in your function.&lt;br /&gt;
&lt;br /&gt;
See Example [[#Validate_Field_Function|Validate Field Function]].&lt;br /&gt;
====== Filter Event ======&lt;br /&gt;
The Filter function is the most versatile function. This function can be used to unpack the record data so it can be properly displayed in the listview. It can also mark records for inclusion or exclusion in the listview, and if it specifies a color, then that color is used to conditionally color the records of the data file while displaying them in the listview.&lt;br /&gt;
&lt;br /&gt;
Your filter function must return true (non-zero) or something (non-empty string) for all records which are to be included in the listview. Any time your Filter Function returns False (or a null string), the record is ignored.&lt;br /&gt;
&lt;br /&gt;
See Example [[#Listview_Filter_Function|Listview Filter Function]].&lt;br /&gt;
====== Conversion Function ======&lt;br /&gt;
The Conversion Function Event is more powerful then many of the other events. It can also contain a function or a reference to a library, but in addition to those values it may contain any valid BR PIC or FMT or DATE statement that can be applied with the &amp;quot;CNVRT$&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
Also, if you&#039;re using BR 4.2, the Conversion function may be used with Listview Columns to natively support numeric listview columns.&lt;br /&gt;
&lt;br /&gt;
If the conversion value is DATE then ScreenIO will automatically use it to convert what the user typed in back into a natural DATE value.&lt;br /&gt;
&lt;br /&gt;
You may also use the validation function to preform validation on the field. However, if you are using DATE, then remember to leave the accpted value in the DATE format so that ScreenIO can convert it back to the julian DAYS format that you will be saving on disk.&lt;br /&gt;
&lt;br /&gt;
If the conversion value is PIC or FMT then ScreenIO will not attempt to convert it back, but it will still use &amp;quot;val&amp;quot; to change numeric fields back into numeric fields.&lt;br /&gt;
&lt;br /&gt;
If the conversion value is a custom function, then your custom function will need to modify &amp;quot;FieldText$&amp;quot; to the appropriate value for Converting from Disk to Screen. If you then need to convert it back, you may do so through the fields Validation function.&lt;br /&gt;
&lt;br /&gt;
==== Valid Custom Function Types ====&lt;br /&gt;
Your Custom Function can specify several different types of Event Handler. The Edit button is provided to help you manage and reuse your Custom Functions. &lt;br /&gt;
&lt;br /&gt;
If you wish to enter any of the other types of Event Handlers, simply type them into the Event Textbox.&lt;br /&gt;
&lt;br /&gt;
===== Link to another screen =====&lt;br /&gt;
To link to another screen, simply specify the Screen Name in Square Brackets:&lt;br /&gt;
&lt;br /&gt;
  Function: [CUSTEDIT]&lt;br /&gt;
  &lt;br /&gt;
  or (specify a position)&lt;br /&gt;
  &lt;br /&gt;
  Function: [CUSTEDIT(2,4)]&lt;br /&gt;
  &lt;br /&gt;
  or (pass in other values)&lt;br /&gt;
  &lt;br /&gt;
  Function: [CUSTEDIT]key$=CurrentKey$&lt;br /&gt;
&lt;br /&gt;
You can specify the row and column position to place the new screen using the shorthand notation specified above, placing the row and column in parenthesis inside the square brackets, after the screen name.&lt;br /&gt;
&lt;br /&gt;
You can pass values into the screen you are about to call by specifying them after the name of the screen as in the example above.&lt;br /&gt;
&lt;br /&gt;
You can pass Key$ and ParentKey$, Displayonly, ParentWindow, Dontredolistview, and Record.&lt;br /&gt;
&lt;br /&gt;
====== CurrentKey$ ======&lt;br /&gt;
&lt;br /&gt;
CurrentKey$ always matches the Currently Selected Key from this current screen. If the current screen is a listview, then CurrentKey$ will always match the currently selected row of the listview. This can be used anywhere in your custom functions that you want to know the key for the currently selected or currently edited record.&lt;br /&gt;
&lt;br /&gt;
By saying &amp;quot;Key$=CurrentKey$&amp;quot; in the above example, we are telling the CUSTEDIT screen to use the currently selected listview item as the key for Editing.&lt;br /&gt;
&lt;br /&gt;
====== ThisParentKey$ ======&lt;br /&gt;
&lt;br /&gt;
ThisParentKey$ always matches the parentkey passed into the screen. In most of your custom functions you can just use &amp;quot;ParentKey$&amp;quot; to get this value. However, when calling another screen automatically, if you want to pass the current ParentKey$ into the screen you&#039;re calling, you&#039;ll need to use ThisParentKey$.&lt;br /&gt;
&lt;br /&gt;
If you say &amp;quot;ParentKey$=ThisParentKey$&amp;quot; then you&#039;re telling screenio to use the ParentKey$ from this screen to set the ParentKey$ in the new child screen. This is useful when you need to pass your ParentKey$ or part of it into a child screen as the parentkey for that child screen.&lt;br /&gt;
&lt;br /&gt;
===== Chain statement =====&lt;br /&gt;
If the first character of your function is a %, then the rest of your function is interpreted to be a chain statement.&lt;br /&gt;
&lt;br /&gt;
  %menu.br&lt;br /&gt;
&lt;br /&gt;
This example will chain to the BR program called &amp;quot;menu.br&amp;quot;.&lt;br /&gt;
===== Any single BR command =====&lt;br /&gt;
For most events, anything else you type is interpreted as a regular BR statement and executed with the execute command.&lt;br /&gt;
&lt;br /&gt;
The only exception to this is the Conversion Function. If you type anything else in the Conversion Function, then it will be interpreted as a BR Field Spec to be used with the CNVRT$ function. &lt;br /&gt;
&lt;br /&gt;
You can launch a web page or a system command here, or you can modify the status of the current screen. You might have a Save button with a click event that says:&lt;br /&gt;
&lt;br /&gt;
  let ExitMode=SaveAndQuit&lt;br /&gt;
&lt;br /&gt;
[[#ExitMode|ExitMode]] is the ScreenIO variable that determines when we are done processing your screen. If you set ExitMode to the constant &amp;quot;SaveAndQuit&amp;quot; then your screen will exit and save the data on its way out.&lt;br /&gt;
&lt;br /&gt;
===== Any valid BR Field Spec (Conversion Function Only) =====&lt;br /&gt;
If you type anything in the Conversion Function thats not a library call or a custom function reference, then it will be interpreted as a BR Field Spec to be used with the CNVRT$ function. Any valid field spec, including FMT and PIC and DATE are acceptable here.&lt;br /&gt;
&lt;br /&gt;
ScreenIO will use this value to convert the data as best it can both onto the screen and back onto the disk. If you are using Julian Date values on the disk, you&#039;ll probably want to specify a &amp;quot;DATE(&amp;quot; conversion function to automatically have those displayed and edited as readable dates. You can also use this for numeric formatting, and listview sorting if you put it in a listview column.&lt;br /&gt;
&lt;br /&gt;
Listview numeric column sorting is only available in BR 4.2. BR 4.1 and earlier will sort the numeric fields alphabetically which does not always produce the desired results.&lt;br /&gt;
&lt;br /&gt;
===== Link to a Custom Screen Function =====&lt;br /&gt;
To link to a Custom Screen Function, use the Edit Button. Your selected Custom Screen Function will be placed within Curly Braces {}.&lt;br /&gt;
&lt;br /&gt;
  {AddNewCustomer}&lt;br /&gt;
&lt;br /&gt;
More details about Custom Screen Functions follow.&lt;br /&gt;
&lt;br /&gt;
====== Entering / Selecting your custom handler ======&lt;br /&gt;
To select the Custom Screen Function for a given ScreenIO Event, simply go to the correct place and click the &amp;quot;Edit&amp;quot; button. This button brings up the ScreenIO Select Custom Screen Function dialog.&lt;br /&gt;
&lt;br /&gt;
At the top left you&#039;ll see a list of all your available Custom Screen Functions. At the bottom left is a search box, that can be used to hunt quickly through the list of Custom Screen Functions, as well as to specify the name for new Custom Screen Functions that you might create. At the right of the dialog is a multi-line text box displaying the first part of the source code for the currently selected Custom Screen Function.&lt;br /&gt;
&lt;br /&gt;
You can select any Custom Function from the list and click the &amp;quot;Ok&amp;quot; button to accept it.&lt;br /&gt;
&lt;br /&gt;
===== Link to a Library Function =====&lt;br /&gt;
You may also link directly to a library function from any of your Screen Events. To do this, type a &amp;quot;#&amp;quot; followed by the library name and the function, separated by a &amp;quot;:&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  #libname:fnFunctionName(parm1,parm2$,parm3)&lt;br /&gt;
&lt;br /&gt;
Example: Assume your library is called &amp;quot;run.br&amp;quot; and your function is called fnRun(screenname$).&lt;br /&gt;
&lt;br /&gt;
  #run:fnRun(&#039;customer&#039;)&lt;br /&gt;
&lt;br /&gt;
Example 2: Assume your library is called &amp;quot;thing.dll&amp;quot; and your function is called fnDoSomething(thing$,otherthing$)&lt;br /&gt;
&lt;br /&gt;
  #thing.dll:fnDoSomething(thing$,&#039;constant&#039;)&lt;br /&gt;
&lt;br /&gt;
Note: Notice the use of single quotes when passing string constants into your library functions. This is necessary at this time because of the way ScreenIO compiles your custom helper libraries.&lt;br /&gt;
&lt;br /&gt;
==== Writing Screen Helper Functions ====&lt;br /&gt;
&lt;br /&gt;
To create a new Custom Screen Function, enter a name into the search box at the bottom left and click the &amp;quot;Add New&amp;quot; button. ScreenIO automatically creates a new .brs file containing a blank custom screen function, and opens it in your Windows Default Editor for .BRS files. If you don&#039;t have a default editor specified yet, then select MyEDIT or some other editor capable of working with .BRS files.&lt;br /&gt;
&lt;br /&gt;
You will notice that your new blank Custom Screen Function doesn&#039;t have any line numbers in it. This is important. When ScreenIO compiles all your individual Custom Screen Functions into one Autogenerated Screen Helper Library for each Screen, it has to add the line numbers itself, to make sure that none of them conflict with each other. Therefore, when you write Custom Screen Functions, it is important to remember not to use line numbers in your code.&lt;br /&gt;
&lt;br /&gt;
===== Custom Screen Function Parameters =====&lt;br /&gt;
&lt;br /&gt;
ScreenIO Provides several parameters automatically that you can use in your Screen Functions. If you wish to make use of a parameter, all you have to do is add it as a required parameter in your Custom Function Definition statement. ScreenIO actually checks your custom function statements to see which variables they are expecting and provides them with all the variables they ask for, as long as they are on this list:&lt;br /&gt;
&lt;br /&gt;
*&#039;&#039;&#039;Function$&#039;&#039;&#039; - The Function we are Calling&lt;br /&gt;
*&#039;&#039;&#039;Mat F$&#039;&#039;&#039; - The Strings for the FileIO Record Object&lt;br /&gt;
*&#039;&#039;&#039;Mat F&#039;&#039;&#039; - The Numbers for the FileIO Record Object&lt;br /&gt;
*&#039;&#039;&#039;Mat S$&#039;&#039;&#039; - Your Screen Record Object&lt;br /&gt;
*&#039;&#039;&#039;Mat Form$&#039;&#039;&#039; - Your FileIO Forms Array&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;All your Screen Information&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
**&#039;&#039;&#039;Mat Screenio$&#039;&#039;&#039; - Your Screen Header information (Strings)&lt;br /&gt;
**&#039;&#039;&#039;Mat Screenio&#039;&#039;&#039; - Your Screen Lines information (Numbers)&lt;br /&gt;
**&#039;&#039;&#039;mat ControlName$&#039;&#039;&#039; - Array of the control names for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat FieldName$&#039;&#039;&#039; - Array of the Field Names for the associated fields of all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat Description$&#039;&#039;&#039; - Array of the Descriptions or Caption Fields for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat VPosition&#039;&#039;&#039; - Array of the Verticle Position for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat HPosition&#039;&#039;&#039; - Array of the Horizontal Position for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat FieldType$&#039;&#039;&#039; - Array of the Field Types for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat SpecWidth&#039;&#039;&#039; - Array of the Spec Widths for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat Width&#039;&#039;&#039; - Array of the Widths for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat Height&#039;&#039;&#039; - Array of the Heights for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat TrueValue$&#039;&#039;&#039; - Array of the Truth Values for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat FalseValue$&#039;&#039;&#039; - Array of the Falsehood Values for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat Function$&#039;&#039;&#039; - Array of the Function triggers for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat Picture$&#039;&#039;&#039; - Array of the Picture Files for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat Parent$&#039;&#039;&#039; - Array of the Parent Attribute for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat FGColor$&#039;&#039;&#039; - Array of the Foreground Colors for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat BGColor$&#039;&#039;&#039; - Array of the Background Colors for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat Justify$&#039;&#039;&#039; - Array of the Justification Specs for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat Attr$&#039;&#039;&#039; - Array of the Additional Attribute Specs for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat Protected&#039;&#039;&#039; - Array of boolean flag indicating weather or not each of your controls are protected.&lt;br /&gt;
**&#039;&#039;&#039;mat Invisible&#039;&#039;&#039; - Array of boolean flag indicating weather or not each of your controls are invisible.&lt;br /&gt;
**&#039;&#039;&#039;mat Tooltip$&#039;&#039;&#039; - Array of the tooltip help text for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat ConvrtIn$&#039;&#039;&#039; - Array of the conversion values for all the controls on your screen.&lt;br /&gt;
**&#039;&#039;&#039;mat ConvrtOut$&#039;&#039;&#039; - Not currently used.&lt;br /&gt;
**&#039;&#039;&#039;mat MultiSelect&#039;&#039;&#039; - Array of values indicating weather or not your Listviews have Multiselect Enabled.&lt;br /&gt;
**&#039;&#039;&#039;mat Userdata$&#039;&#039;&#039; - Array of data passed into your screen that can be used for any reason&lt;br /&gt;
*&#039;&#039;&#039;mat Subscripts$&#039;&#039;&#039; - This array contains your FileIO Subscripts and your ScreenIO Subscripts and the sio_ subscripts for all your controls that are not tied to a field and are instead living inside your mat S$ array.&lt;br /&gt;
*&#039;&#039;&#039;Key$&#039;&#039;&#039; - This is the Key that we called the screen with&lt;br /&gt;
*&#039;&#039;&#039;[[#ExitMode|ExitMode]]&#039;&#039;&#039; - Set [[#ExitMode|ExitMode]] to non-zero to cause your screen to exit.&lt;br /&gt;
*&#039;&#039;&#039;RepopulateListviews&#039;&#039;&#039; - Set this value to True in your function to cause ScreenIO to redraw the listviews when its done processing your custom function code.&lt;br /&gt;
*&#039;&#039;&#039;Prefix$&#039;&#039;&#039; - Prefix for your FileIO Data File&lt;br /&gt;
*&#039;&#039;&#039;Currentkey$&#039;&#039;&#039; - Currently selected key from your data file&lt;br /&gt;
*&#039;&#039;&#039;rec(datafile)&#039;&#039;&#039; - this is obvious, but if you need to know the current record in the primary data file you can use the BR system function REC to discover it.&lt;br /&gt;
*&#039;&#039;&#039;mat SelectedKeys$&#039;&#039;&#039; - If you have a listview with multiselect enabled, use this array to access the keys of all selected records. If Multiselect is not enabled, then this array will have only one element and it will be equivlent to CurrentKey$ above. Therefore you can use Mat SelectedKeys$ to write functions that work for both multi-select listviews and single selection listviews.&lt;br /&gt;
*&#039;&#039;&#039;mat SelectedRecords&#039;&#039;&#039; - If you have a listview with multiselect enabled, use this array to access the record numbers of all selected records. If Multiselect is not enabled, then this array will have only one element and it will be equivlent to rec(Datafile) above. Therefore you can use Mat SelectedRecords to write functions that work for both multi-select listviews and single selection listviews.&lt;br /&gt;
*&#039;&#039;&#039;mat Save_F$&#039;&#039;&#039; - this is an automatic copy of Mat F$ that is made upon entering the screen and can be used to determine weather or not the user has changed anything sense reading or adding the record.&lt;br /&gt;
*&#039;&#039;&#039;mat Save_F&#039;&#039;&#039; - this is an automatic copy of Mat F that is made upon entering the screen and can be used to determine weather or not the user has changed anything sense reading or adding the record.&lt;br /&gt;
*&#039;&#039;&#039;mat Save_S$&#039;&#039;&#039; - this is an automatic copy of mat S$ that is made upon entering the screen and can be used to determine weather or not the user has changed anything sense reading or adding the record.&lt;br /&gt;
*&#039;&#039;&#039;mat PassedData$&#039;&#039;&#039; - this array can be used for any purpose you desire. It represents an array of data you can pass into your screen with the call to fnfm. You can query it and use it in your custom functions in whatever way you desire.&lt;br /&gt;
*&#039;&#039;&#039;Parentkey$&#039;&#039;&#039; - The Parent Key that may have been passed into your screen when it was called. This is a value that you can pass into your screens that has no purpose except to be used in your screen functions. You can use it to filter your listview to show only records for the current Customer or whatver ParentKey makes sense to you.&lt;br /&gt;
*&#039;&#039;&#039;LockUser$&#039;&#039;&#039; - This value is only available in the Record Locked event. It will tell you the user name of the user who has the record locked.&lt;br /&gt;
*&#039;&#039;&#039;Datafile&#039;&#039;&#039; - This is the file number of the data file&lt;br /&gt;
*&#039;&#039;&#039;Window&#039;&#039;&#039; - This is the window number of the screenio screen&lt;br /&gt;
*&#039;&#039;&#039;FileIO Subscripts&#039;&#039;&#039; - All your fileio subscripts are set for you so you may use your file just as if you&#039;d opened it yourself.&lt;br /&gt;
*&#039;&#039;&#039;ScreenIO Subscripts&#039;&#039;&#039; - Any of your screen controls that belong in MAT S$ have a screen subscript that you can use to access them.&lt;br /&gt;
*&#039;&#039;&#039;ScreenIO Control Subscripts&#039;&#039;&#039; - Every Control on your screen with a control name has a subscript that can be used to access its properties in the Screen Control Arrays above. For example, if you have a text box named &amp;quot;Customer&amp;quot; and you want to make it invisible in one of your custom helper functions, then give the command: &amp;quot;let Invisible(ctl_customer)=1&amp;quot;&lt;br /&gt;
*&#039;&#039;&#039;CurrentRow&#039;&#039;&#039; - this variable contains and controls the currently selected listview element. You can use it to determine which listview item is currently selected, and if you change this value it will change the current row in the listview. You can use this value to control the cursor on a listview screen.&lt;br /&gt;
*&#039;&#039;&#039;Currentfield&#039;&#039;&#039; - This is the CurFld Value of the field which the cursor is in. If you change it, it will move the cursor around.&lt;br /&gt;
*&#039;&#039;&#039;Currentfield$&#039;&#039;&#039; - This is Control Name of the Control for the field which the cursor is in. You can move the cursor by setting CurrentField$ to the ControlName$ of the field you want to move it to. This is case insensitive. If you change both CurrentField$ and CurrentField, the CurrentField$ change takes precedence.&lt;br /&gt;
*&#039;&#039;&#039;&#039;&#039;Only Available in Validate and Conversion Functions&#039;&#039;&#039;&#039;&#039; - these next parameters are only available in Validate and Conversion functions. Most of them are read only (any changes to them will be ignored) and they should be used to make your custom Validation and Conversion functions reusable:&lt;br /&gt;
**&#039;&#039;&#039;Fieldtext$&#039;&#039;&#039; - This is the text in the field being validated/converted.&lt;br /&gt;
**&#039;&#039;&#039;Fieldindex (read only)&#039;&#039;&#039; - This is the CurFld value of the field being validated/converted. You could use this to put the cursor in the bad field by saying &#039;&#039;&amp;quot;CurrentField=FieldIndex&amp;quot;&#039;&#039;.&lt;br /&gt;
**&#039;&#039;&#039;ControlIndex (read only)&#039;&#039;&#039; - This is the index (matches ctl_controlname) of the Control for the field being validated/converted. You can use this anywhere that you can use ctl_controlname, for example to access the Attributes arrays of the control. For example, you can make the control invisible by saying &#039;&#039;&amp;quot;Invisible(ControlIndex)=1&amp;quot;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
===== Accessing Control Properties from within your Helper Functions =====&lt;br /&gt;
If you wish to access any of your controls&#039; attributes from a custom helper function, you first have to define the control by giving it a ControlName in the Control Attributes Window. Then, all you have to do is reference the array of the attribute you&#039;re looking for, with the control name for a subscript, prefixed by &amp;quot;ctl_&amp;quot;. For example, to make the customer control invisible, simply type:&lt;br /&gt;
&lt;br /&gt;
  let Invisible(ctl_customer)=1&lt;br /&gt;
&lt;br /&gt;
===== #Include Statement =====&lt;br /&gt;
Sometimes it is necessary to reference one of your custom helper functions from another one. But when you do, you need a way to ensure that its always included in any screens that call the first custom helper function. The way to do that is with the #Include statement. You use this statement in a comment, so that BR will ignore it. Simply say:&lt;br /&gt;
&lt;br /&gt;
  ! #Include {functionname}&lt;br /&gt;
&lt;br /&gt;
in a comment somewhere in your program and the specified custom helper function will be included. The &amp;quot;{}&amp;quot;s are mandatory and are part of the syntax for specifying a Custom Helper Function anywhere in ScreenIO.&lt;br /&gt;
&lt;br /&gt;
===== Examples =====&lt;br /&gt;
&lt;br /&gt;
====== Validate Field Function ======&lt;br /&gt;
&lt;br /&gt;
NOTE: ScreenIO has this functionality built in now, so you shouldn&#039;t need to validate your dates this way. Its only included here as an example for how a validate function works.&lt;br /&gt;
&lt;br /&gt;
For more information on the proper way to work with dates in ScreenIO, see the [[#Conversion_Function|Conversion Function]] section.&lt;br /&gt;
&lt;br /&gt;
  ! function\validatedate.brs&lt;br /&gt;
  !&lt;br /&gt;
  ! Created on 01/12/2009&lt;br /&gt;
  !&lt;br /&gt;
  ! This function would be placed in every field in the SageLive system that accepts a date.&lt;br /&gt;
  ! &lt;br /&gt;
  !&lt;br /&gt;
  def fnvalidatedate(&amp;amp;fieldtext$;___,DateValue)  &lt;br /&gt;
     let DateValue=days(fieldtext$,&amp;quot;mm/dd/ccyy&amp;quot;) conv BadDateEntered&lt;br /&gt;
  &lt;br /&gt;
     let fieldtext$=date$(DateValue,&amp;quot;m/d/ccyy&amp;quot;)&lt;br /&gt;
     let fnvalidatedate=1 ! Date Save Successful  &lt;br /&gt;
  &lt;br /&gt;
     BadDateEntered: ! a bad date was entered. Return False so that ScreenIO Places the old value back.&lt;br /&gt;
  fnend&lt;br /&gt;
&lt;br /&gt;
====== Listview Filter Function ======&lt;br /&gt;
&lt;br /&gt;
  ! function\filtertasks.brs&lt;br /&gt;
  ! Created on 04/17/2009&lt;br /&gt;
  !&lt;br /&gt;
  ! fnFilterTasks - This Function Filters the Tasks List to show only&lt;br /&gt;
  !  tasks for the Current Employee that are not completed or cancelled. &lt;br /&gt;
  !  It also colors the tasks, and sets the task_status Listview Column.&lt;br /&gt;
  !&lt;br /&gt;
  ! This function is the filter event for the Todo List listview in the SageLive System&lt;br /&gt;
  !&lt;br /&gt;
  dim CurrentEmployee$&lt;br /&gt;
  &lt;br /&gt;
  def fnFilterTasks$(mat f$,mat f,ParentKey$,prefix$,mat Subscripts$,mat S$)&lt;br /&gt;
     &lt;br /&gt;
     if CurrentEmployee$=&amp;quot;&amp;quot; then&lt;br /&gt;
        library &amp;quot;timelib&amp;quot; : fnCurrentEmployee$&lt;br /&gt;
        let CurrentEmployee$=fnCurrentEmployee$&lt;br /&gt;
     end if&lt;br /&gt;
     if uprc$(ParentKey$(1:7))=&amp;quot;SHOWALL&amp;quot; then&lt;br /&gt;
        if f$(todo_employee)=CurrentEmployee$ then&lt;br /&gt;
           let fnFilterTasks$=&amp;quot;/#00FF00:#000000&amp;quot;&lt;br /&gt;
        else&lt;br /&gt;
           let fnFilterTasks$=&amp;quot;/#0000FF:#000000&amp;quot;&lt;br /&gt;
        end if&lt;br /&gt;
     else if f$(todo_employee)=CurrentEmployee$ and f(todo_cancel)=0 and f(todo_complete)=0 then&lt;br /&gt;
        let fnFilterTasks$=&amp;quot;/#33CC66:#000000&amp;quot;&lt;br /&gt;
        if sio_taskstatus then let s$(sio_taskstatus)=&amp;quot;X&amp;quot; ! Open&lt;br /&gt;
     else if f$(todo_employee)=CurrentEmployee$ and f(todo_cancel)=0 and f(todo_complete)=days(date$) then&lt;br /&gt;
        let fnFilterTasks$=&amp;quot;/#6699FF:#000000&amp;quot;&lt;br /&gt;
        if sio_taskstatus then let s$(sio_taskstatus)=&amp;quot;Y&amp;quot; ! Completed&lt;br /&gt;
     else if f$(todo_employee)=CurrentEmployee$ and f(todo_cancel)=days(date$) and f(todo_complete)=0 then&lt;br /&gt;
        let fnFilterTasks$=&amp;quot;/#AA0000:#000000&amp;quot;&lt;br /&gt;
        if sio_taskstatus then let s$(sio_taskstatus)=&amp;quot;Z&amp;quot; ! Cancelled&lt;br /&gt;
     end if&lt;br /&gt;
  fnend&lt;br /&gt;
&lt;br /&gt;
====== Click Event Function ======&lt;br /&gt;
&lt;br /&gt;
  ! function\quickinvoiceacustomer.brs&lt;br /&gt;
  ! Created on 03/30/2009&lt;br /&gt;
  !&lt;br /&gt;
  ! fnQuickInvoiceACustomer - This Function automatically creates an invoice&lt;br /&gt;
  !  for a customer.&lt;br /&gt;
  !&lt;br /&gt;
  ! This function is placed in the Click Event for the &amp;quot;Invoice Customer&amp;quot; button on the&lt;br /&gt;
  !  Customer Listview Screen in the SageLive system.&lt;br /&gt;
  !&lt;br /&gt;
  ! It operates on the currently selected item in the listview by using the&lt;br /&gt;
  !  value of CurrentKey$&lt;br /&gt;
  ! &lt;br /&gt;
  ! Most of the actual processing takes place in various libraries that are part&lt;br /&gt;
  !  of the SageLive system.&lt;br /&gt;
    &lt;br /&gt;
  dim Invoice$(1)*255,Invoice(1)&lt;br /&gt;
  &lt;br /&gt;
  def fnQuickInvoiceACustomer(CurrentKey$,DataFile,mat Form$)&lt;br /&gt;
     library &amp;quot;invclib&amp;quot; : fnBuildInvoiceHeader,fnAddCustomerToInvoice,fnImportCustomer, fnPrintInvoiceByData&lt;br /&gt;
  &lt;br /&gt;
     let Invoice=fnOpen(&amp;quot;invoice&amp;quot;,mat Invoice$,mat Invoice,mat Form$)&lt;br /&gt;
  &lt;br /&gt;
     let fnBuildInvoiceHeader(Invoice,mat Invoice$,mat Invoice)&lt;br /&gt;
     let fnAddCustomerToInvoice(CurrentKey$,mat Invoice$,mat Invoice,DataFile,mat form$)&lt;br /&gt;
     let fnImportCustomer(CurrentKey$,Invoice$(ih_id))&lt;br /&gt;
     let fnPrintInvoiceByData(mat Invoice$,mat Invoice,1)&lt;br /&gt;
  &lt;br /&gt;
     write #Invoice, using form$(Invoice) : mat Invoice$, mat Invoice&lt;br /&gt;
     let fnCloseFile(Invoice,&amp;quot;invoice&amp;quot;)&lt;br /&gt;
  &lt;br /&gt;
     let fnfm(&#039;INVCEDIT&#039;,Invoice$(ih_id))&lt;br /&gt;
  fnend&lt;br /&gt;
&lt;br /&gt;
The first function called, fnBuildInvoiceHeader, populates the Invoice Header information with the current date and the next available invoice number, etc.&lt;br /&gt;
&lt;br /&gt;
The next two functions, fnAddCustomerToInvoice and fnImportCustomer add the customer to the invoice, automatically searching the database for any billable work that has been completed, and adding it to the invoice. They also mark the timelog records as &amp;quot;Billed&amp;quot;, and mark the invoice number in the timelog record showing which invoice each timelog entry ended up on. At the same time, they populate the Invoice Header record with important information such as Billing Address, Shipping Information, Payment Terms, etc.&lt;br /&gt;
&lt;br /&gt;
The next function, fnPrintInvoiceByData generates the invoice as a PDF file. It automatically detects if we&#039;re running BR 4.2 or 4.1. If we&#039;re running BR 4.1, then it generates the PDF file using the CutePDF Printer Driver and a short AutoIt Script. If its BR 4.2, then it uses the built in PDF generation ability. The optional parameter 1 at the end specifies to generate the PDF file. The same function could be used to print the invoice on a standard printer using Print Preview and the windows Printer selection dialog.&lt;br /&gt;
&lt;br /&gt;
After that we write the new invoice to the database, and the file is closed.&lt;br /&gt;
&lt;br /&gt;
Finally, the Edit Invoice screen is called, and the new invoice is displayed to be reviewed and emailed to the customer.&lt;br /&gt;
&lt;br /&gt;
When the user is finished looking at the invoice, we return to what we were doing in the customer screen.&lt;br /&gt;
&lt;br /&gt;
====== Mainloop Function ======&lt;br /&gt;
&lt;br /&gt;
Now lets take a look at how to use the Mainloop Function to respond to various keys.&lt;br /&gt;
&lt;br /&gt;
  ! function\tabsmainloop.brs&lt;br /&gt;
  ! Created on 02/21/2010&lt;br /&gt;
  !&lt;br /&gt;
  ! fnTabsMainloop - This Function This Function updates the Current Potential&lt;br /&gt;
  !  elements of the Screen (if they exist)&lt;br /&gt;
  !&lt;br /&gt;
  ! This function appears in many of the SageLive screens, to enable the Windows Dropdown Menu.&lt;br /&gt;
  !  it also does a few other things for some of the screens it sits in.&lt;br /&gt;
  !&lt;br /&gt;
  ! #Include {executetask}&lt;br /&gt;
  ! #Include {tabwindowsmenu}&lt;br /&gt;
  &lt;br /&gt;
    def fnTabsMainloop&lt;br /&gt;
       if fkey=98 then let fnProcessWindowsMenu  ! Fkey 98 is Windows Menu Click&lt;br /&gt;
       if fkey=0 or fkey=201 then let fnSelect   ! Fkey 0 is Enter and Fkey 201 is Double Click&lt;br /&gt;
  &lt;br /&gt;
       if sio_current_potential or sio_current_week_now or sio_current_week_poten then let fnUpdateCurrentPotential&lt;br /&gt;
    fnend&lt;br /&gt;
   &lt;br /&gt;
    def fnSelect&lt;br /&gt;
       if lwrc$(screenio$(si_screencode))=&amp;quot;tabwork&amp;quot; then&lt;br /&gt;
          let fnfm(&amp;quot;projedit&amp;quot;,CurrentKey$)&lt;br /&gt;
       else if lwrc$(screenio$(si_screencode))=&amp;quot;tabtodo&amp;quot; then&lt;br /&gt;
          if todo_function and len(trim$(f$(todo_function))) then&lt;br /&gt;
             let fnExecuteTask&lt;br /&gt;
          else&lt;br /&gt;
             let fnfm(&amp;quot;taskedit&amp;quot;,CurrentKey$)&lt;br /&gt;
          end if&lt;br /&gt;
       else if lwrc$(screenio$(si_screencode))=&amp;quot;tabincome&amp;quot; then&lt;br /&gt;
          let fnfm(&amp;quot;invcedit&amp;quot;,CurrentKey$)&lt;br /&gt;
       else if lwrc$(screenio$(si_screencode))=&amp;quot;tabexpense&amp;quot; then&lt;br /&gt;
          let fnfm(&amp;quot;expnedit&amp;quot;,CurrentKey$)&lt;br /&gt;
       else if lwrc$(screenio$(si_screencode))=&amp;quot;tabcustomer&amp;quot; then&lt;br /&gt;
          let fnfm(&amp;quot;custedit&amp;quot;,CurrentKey$)&lt;br /&gt;
       end if&lt;br /&gt;
       if fkey&amp;lt;&amp;gt;93 then let fkey(-1) ! Reset Fkey after whatever they&#039;ve done except Windows X&lt;br /&gt;
       let Function=-1&lt;br /&gt;
       let ExitMode=0 ! Don&#039;t exit after procesing Enter Key&lt;br /&gt;
    fnend&lt;br /&gt;
&lt;br /&gt;
The fnTabsMainLoop function is used here to check for various special function keys that we want to do something special for, as well as to do any processing that we wish to run as often as possible.&lt;br /&gt;
&lt;br /&gt;
The first thing it does is test for and respond to a Windows Dropdown Menu click (fkey 98). If a selection is made from the Windows Dropdown Menu, the SageLive Windows Menu handler is called. This Windows Menu Handler function resides in another Custom Function which we include using the #Include screenio command. This command is used any time one of your custom functions depends on another custom function.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After that we check for the Enter Key (fkey 0) or a Double Click (fkey 201). The default action in ScreenIO for the enter key, is to select the current item from the list and return it to the calling code, exiting the screen. But for many of the listveiws in the SageLive system, we wanted to do something different. In many cases we wanted to view or edit the item selected, and in one case, the SageLive Todo List, we wanted to do something really special.&lt;br /&gt;
&lt;br /&gt;
We&#039;re testing for fkey 201 because I also want double clicking on a listview item to preform our special &amp;quot;Selection&amp;quot; routine.&lt;br /&gt;
&lt;br /&gt;
Because this function is used in many different screens, and they each display different information and require a different action, I chose to place the code that handles the event inside another function, fnSelect.&lt;br /&gt;
&lt;br /&gt;
FnSelect tests the value of the ScreenCode in mat ScreenIO$ to see which screen we&#039;re in, and handles the click accordingly. For example, if we&#039;re on the Customer screen, then double clicking launches the Customer Edit screen, displaying the current customer record. If we&#039;re on the Expense Screen, then we want to launch the Expense Edit screen to view or edit the Expense Record.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The SageLive Todo List contains one special feature. Todo List Items can have code in them, a function that gets executed automatically to help with the task. For example, the automatic task that comes up each month to remind me to enter the electric bill has code in it that helps me enter the electric bill as an expense into the system.&lt;br /&gt;
&lt;br /&gt;
When I run that task, SageLive automatically launches my electric bills website for me, right at the login prompt. Then it waits with an autoit script for me to print the latest bill from their webpage. I select &amp;quot;Print Bill&amp;quot; from the electric companies website, and the bill is snatched right from the print stream and uploaded into SageLive. I read and enter the amount on the bill, and the rest is done for me.&lt;br /&gt;
&lt;br /&gt;
Here you see where we call the ExecuteTask function responsible for that piece of magic, whenever an item is selected on the SageLive Todo List. If the Task we selected has code in it, then we run the code, executing the task. If it does not have code in it, then we simply launch the Task View screen where the text in the Todo List item can be read in a multi-line text box.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
At the end of the fnSelect Routine is code to reset the fkey value and to cancel the default action for the Enter key (which is to select and quit). Fkey 93 is the Windows X, and in ScreenIO it means to exit every screen that we&#039;re in (prompting to save any changes) and if your original calling program that launched the first screen responds to it properly, close BR. So we want to leave fkey 93 alone but cancel any other fkey values that might have come back from the screen we jumped into.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
After handling the special keys, our fnTabsMainLoop function handles the fnUpdateCurrentPotential. Some of the screens in the SageLive system have a little place where they show the Current Employee&#039;s Current Potential Earnings. This function is called from lots of screens and only a few of those have the Current Potential Display, so the first thing we do is test to see if the screen we&#039;re currently in has the Current Potential fields on it. &lt;br /&gt;
&lt;br /&gt;
The Current Potential Fields is a calculated approximation of how much money the Current Employee has earned so far today, and how much money they can potentially earn if they continue to work until 6pm.&lt;br /&gt;
&lt;br /&gt;
It was intended to be a motivational tool, but its mentioned here as an example of a situation where you might want to update some data on the screen as often as possible. Because the Current Earnings are always going up whenever the employee is currently logged in on a project, and the Potential Earnings are always going down whenever the employee is not logged in on a project, we want to try to update it as often as we can.&lt;br /&gt;
&lt;br /&gt;
The mainloop is called every single time ScreenIO gets control and the RINPUT FIELDS statement ends. The Screens with Current Potential fields are all listview screens with the X attribute specified for the listview, making it so that any time the user scrolls around the list, presses the fkey, clicks on any button or does just about anything at all, the Current Potential is updated. You can even use this in combination with the Wait Time value to force a regular update of the screen.&lt;br /&gt;
&lt;br /&gt;
===== ScreenIO Built In functions =====&lt;br /&gt;
ScreenIO has a built in function for use in your events.&lt;br /&gt;
====== FnFindSubscript ======&lt;br /&gt;
FnFindSubscript(mat Subscripts$,Prefix$,String$)&lt;br /&gt;
This function searches through the array mat Subscripts$ looking for the subscript that matches the given Prefix$ and Subname$. It returns the index of this subscript.&lt;br /&gt;
&lt;br /&gt;
Use this function to programmatically interrogate mat Subscripts$ from your Custom Functions in order to help make them more reusable.&lt;br /&gt;
&lt;br /&gt;
===== Mat S$ =====&lt;br /&gt;
Lets go over a couple of ScreenIO Concepts one more time.&lt;br /&gt;
&lt;br /&gt;
Most of the controls on the screen are tied directly to a field in the data file. In your Custom Validation Functions, you can refer to that data by its FileIO Name.&lt;br /&gt;
&lt;br /&gt;
  let msgbox(&amp;quot;Customer Name is &amp;quot;&amp;amp;f$(cu_Name))&lt;br /&gt;
&lt;br /&gt;
The value in your mat F$ and mat F is the same as the value on the screen. It is the value of the disk record in memory. When the record is saved, mat F$ and mat F are rewritten back to the data file.&lt;br /&gt;
&lt;br /&gt;
However, any of your controls that are NOT tied to a data file, (but still have a control name) get placed in another array: Mat S$&lt;br /&gt;
&lt;br /&gt;
A Control is tied to the data file if it has a value for its FieldName. Mat S$ contains the data for all the controls that have no value for &amp;quot;FieldName&amp;quot; but do have a value for &amp;quot;ControlName&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
You can access them the data in Mat S$ by giving the screenIO subscript for the control, which is sio_ControlName where ControlName is the actual name of your control.&lt;br /&gt;
&lt;br /&gt;
  read #CustomerFile, using form$(CustomerFile), key=f$(ih_customer) : mat Customer$, mat Customer&lt;br /&gt;
  let S$(sio_CustomerName)=Customer$(cu_FirstName)&amp;amp;&amp;quot; &amp;quot;&amp;amp;Customer$(cu_LastName)&lt;br /&gt;
&lt;br /&gt;
You can use this feature to have additional input fields that the end user is able to interact with that don&#039;t necessarily correspond directly with a field in the data file. Your Custom Functions can react to the mat S$ fields and they can also update the Mat S$ fields.&lt;br /&gt;
&lt;br /&gt;
You can use a Mat S$ field to set the picture file for a picture control, to something that is calculated in a Custom Function at runtime.&lt;br /&gt;
&lt;br /&gt;
===== ExitMode =====&lt;br /&gt;
&lt;br /&gt;
One common thing you might do in a custom function, or directly in one of your controls Function properties is set ExitMode. ExitMode is a variable you can change with your custom functions. It governs when your screen is finished executing.&lt;br /&gt;
&lt;br /&gt;
ExitMode can have the following values:&lt;br /&gt;
&lt;br /&gt;
*ExitMode=0 .... When ExitMode is 0 the screen keeps running. You can cancel an ExitMode by setting it back to 0.&lt;br /&gt;
*ExitMode=SaveAndQuit .... When ExitMode is SaveAndQuit then the screen stops running and the data is saved and the key of the new record is returned. Use this on an Add/Edit Screen.&lt;br /&gt;
*ExitMode=SelectAndQuit .... When ExitMode is SelectAndQuit then the screen stops running and the key of the currently selected listview item is returned. Use this on a Listview Screen.&lt;br /&gt;
*ExitMode=QuitOnly .... When ExitMode is QuitOnly the screen stops running and the users data is not saved, and nothing is returned.&lt;br /&gt;
*ExitMode=QuitOther .... QuitOther works the same as SelectAndQuit. You can use it if you need to implement your own custom Exit logic.&lt;br /&gt;
*ExitMode=AskSaveAndQuit .... AskSaveAndQuit will check to see if the user has changed anything. If they have, it will ask the user if they&#039;d like to Save or just Quit, and behave accordingly. If the user hasn&#039;t changed anything, it will just quit.&lt;br /&gt;
&lt;br /&gt;
To set ExitMode in one of your functions, simply assign it a value from the list above.&lt;br /&gt;
&lt;br /&gt;
====== ScreenIO ExitMode Constants ======&lt;br /&gt;
SaveAndQuit, SelectAndQuit and all the other values above are ScreenIO ExitMode Constants. The ScreenIO ExitMode Constants are set for you in your custom helper library in order to help facilitate the readability of your ScreenIO Code. The values are set with code such as the following, and even inside ScreenIO they&#039;re tested for by name.&lt;br /&gt;
&lt;br /&gt;
  let Quitonly=1&lt;br /&gt;
  let Saveandquit=2&lt;br /&gt;
  let Selectandquit=3&lt;br /&gt;
  let Quitother=4&lt;br /&gt;
  let Asksaveandquit=5&lt;br /&gt;
&lt;br /&gt;
=== Working with the ScreenIO Loading Icon ===&lt;br /&gt;
&lt;br /&gt;
ScreenIO comes with an Animated Loading Icon that automatically appears whenever a listview takes a long time to load. This tells the user that something is happening, so they know its not just hung.&lt;br /&gt;
&lt;br /&gt;
You don&#039;t have to do anything to your screens to use the loading animation. It automatically happens whenever a listview takes more then a couple seconds to load.&lt;br /&gt;
&lt;br /&gt;
==== Changing the Loading Icon ====&lt;br /&gt;
&lt;br /&gt;
ScreenIO comes with two different animtated loading icons: A Modern Clock and a Grandfather Clock.&lt;br /&gt;
&lt;br /&gt;
If you look in the &amp;quot;clocks&amp;quot; folder that came with ScreenIO, you&#039;ll see three folders: &amp;quot;clock&amp;quot;, &amp;quot;grandfather clock&amp;quot; and &amp;quot;kitchen clock&amp;quot;. ScreenIO ignores all the other folders, and only looks inside the &amp;quot;clock&amp;quot; folder.&lt;br /&gt;
&lt;br /&gt;
To change which clock you want to use, simply delete the contents of the &amp;quot;clock&amp;quot; folder and replace them with the contents of the one of the other folders, the one containing the clock of your choice.&lt;br /&gt;
&lt;br /&gt;
==== Making your own clock animations ====&lt;br /&gt;
&lt;br /&gt;
Its very simple to make your own clock animations. All you have to do is place a bunch of image files in a folder, depicting the different steps of the animation. They can be either jpg&#039;s or gif&#039;s. You can have as many files as you want, and they can be any resolution you want, but keep in mind that large animations may run slow in network or internet environments. If you intend to run your software over a network share, or over Client Server, you may wish to stick to reasonably sized files. You can get plenty of detail for a loading animation out of a 2k image file.&lt;br /&gt;
&lt;br /&gt;
Gif files are particularly nice to work with because they support transparency, so your loading clock doesn&#039;t have to be square.&lt;br /&gt;
&lt;br /&gt;
ScreenIO reads all the images in the clocks\clock folder and sorts them alphabetically, then plays them in a loop. The timing and size and color of the animation window is controlled via the clock.ini settings file.&lt;br /&gt;
&lt;br /&gt;
===== The clock.ini settings file =====&lt;br /&gt;
&lt;br /&gt;
In your clock folders, you&#039;ll see a clock.ini settings file. Its a very short csv file containing five fields in order. All of the fields are optional. The Clock.ini file itself is optional, in fact. If the file is not found, or any of the values are missing, then default values are used.&lt;br /&gt;
&lt;br /&gt;
The five parameters, and their default values are as follows:&lt;br /&gt;
&lt;br /&gt;
#) Animation Speed (.5) - This is the Animation Speed, in seconds of delay. The default value will update the animation every half second. Use a lower value for a smoother animation, but be careful, if you use too low of a value you can slow down the processing of the listview. This number should be specific to the animation you&#039;re using. If your frames are very different from each other you&#039;ll want a high value like .5 or .6. If the frames are only changed slightly from each other, and you have a lot of them, then you might want the animation to play faster, like .1 or .2. An animation speed of 0 will force it to update as often as possible, which is one frame each time another chunk of data is sent to the listview.&lt;br /&gt;
#) Rows (5) - The size of the animation window in Rows.&lt;br /&gt;
#) Cols (10) - The size of the animation window in Columns.&lt;br /&gt;
#) Color$ (inherited) - The  BR color for the animation window. If present, this parameter is what goes in the &amp;quot;N=&amp;quot; part of the open statement. The default of none causes BR to use the default or inherited colors for the animation window.&lt;br /&gt;
#) Border$ (no border) - The BR border string for the animation window. This can be used to add or color a BR border.&lt;br /&gt;
&lt;br /&gt;
==== Submitting your clock animations ====&lt;br /&gt;
&lt;br /&gt;
If you&#039;ve made a nice clock, and you&#039;d like to submit it to be included in future releases of ScreenIO, please zip the entire clocks folder and email it to me at gabriel.bakker@gmail.com. I welcome and encourage your submissions, and I look forward to seeing the beautiful loading clocks that you come up with.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Keyboard Reference (Undo/Redo, Copy/Cut/Paste and more) ===&lt;br /&gt;
When using ScreenIO, there are several ways to control the designer with the keyboard. Almost any function can be accessed from the Windows Dropdown Menu, which you can get to from the keyboard by using the Alt key in combination with the underlined letters in the Menu, and with the arrow keys.&lt;br /&gt;
&lt;br /&gt;
You can also use following keyboard shortcuts any time in the ScreenIO Designer.&lt;br /&gt;
&lt;br /&gt;
  Ctrl-V .. Paste Controls&lt;br /&gt;
  Ctrl-X .. Cut Controls&lt;br /&gt;
  Ctrl-C .. Copy Controls&lt;br /&gt;
  Alt-Z ... Undo&lt;br /&gt;
  Alt-R ... Redo&lt;br /&gt;
&lt;br /&gt;
You can use standard keys for Copy, Cut, and Paste in screenio. Copy and Cut act on the current controls and copy them to the clipboard. They are copied to the clipboard in plain text, so its possible to paste them in notepad and then later select them and copy and paste them back into another ScreenIO screen. You can use the clipboard the same way you would expect to use it in any windows program.&lt;br /&gt;
&lt;br /&gt;
Alt-Z and Alt-R Undo and Redo the last operations. You can use them any time in ScreenIO. The only reason its not the standard Ctrl-Z and Ctrl-R is because BR reacts better to Alt-Z and Alt-R.&lt;br /&gt;
&lt;br /&gt;
==== Screen Control Movement Mode ====&lt;br /&gt;
The following controls work in Control Movement Mode Only&lt;br /&gt;
&lt;br /&gt;
  Lf ...... Move the control left&lt;br /&gt;
  Rt ...... Move the control to the right&lt;br /&gt;
  Up ...... Move the control up&lt;br /&gt;
  Dn ...... Move the control down&lt;br /&gt;
  Space ... Make the control Wider&lt;br /&gt;
  BkSp .... Make the control narrower&lt;br /&gt;
  PgDn .... Make the control taller&lt;br /&gt;
  PgUp .... Make the control shorter&lt;br /&gt;
  Enter ... Cycle through the Control Attributes and Movement Mode&lt;br /&gt;
  Del ..... Delete the selected control from the screen&lt;br /&gt;
  Ctrl-S .. Toggle Selection for current control&lt;br /&gt;
  Ctrl-T .. Select All Textboxes&lt;br /&gt;
  Esc ..... Unselect all or exit the current control&lt;br /&gt;
  Ctrl-E .. Make all Left Edges of selected controls match the current control&lt;br /&gt;
  Ctrl-R .. Make all Right Edges of Selected Controls match the current control&lt;br /&gt;
  Ctrl-W .. Make all Widths of selected controls match the current control&lt;br /&gt;
&lt;br /&gt;
===== Selecting Multiple Controls =====&lt;br /&gt;
&lt;br /&gt;
You can use CTRL-S to toggle the selection of the current control, turning it Green, building a group of selected controls. Once you have a bunch of controls selected you can change their attributes or position as a group, instead of having to work with them one at a time.&lt;br /&gt;
&lt;br /&gt;
To select a group of controls, simply click on the controls you want to select one at a time, and press CTRL-S between each click to select them.&lt;br /&gt;
&lt;br /&gt;
The easiest way to learn about control grouping is to try it out. Save your screen and experiment with selecting several controls to see what happens.&lt;br /&gt;
&lt;br /&gt;
The current control will always appear in yellow, and all the controls in the currently selected group will appear in green.&lt;br /&gt;
&lt;br /&gt;
If you move any control, the other selected controls will move with you. You can retain the selection outside of control movement mode but you must be in control movement mode in order to change the selection. Outside of control movement mode the only effects that are shared with the group Copy and Cut, and changing properties. If you change any control properties while there is a selected control group, then a message box will appear asking if you would like to copy the changes to all selected controls in the group.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;You can also move controls around the screen with the mouse. For more information on Mouse Movement, see the chapter on [[#Click_to_Move_Control_Movement|Mouse Movement]].&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Update Process==&lt;br /&gt;
&lt;br /&gt;
If you used an older version of ScreenIO and updated it to a newer version and you recieved a message from ScreenIO saying that it needs to recompile your helper libraries and update your folder structure, thats because we have recently moved all your ScreenIO Helper Libraries into their own subdirectory, in order to keep from cluttering up your main installation directory as much as possible.&lt;br /&gt;
&lt;br /&gt;
If you do not get this message when updating, don&#039;t worry about it. Chances are you were already running with a newer version of ScreenIO. But if you do get this message, then here is a little more information about what it is and what it means.&lt;br /&gt;
&lt;br /&gt;
Your ScreenIO Helper Libraries have been moved into a new folder called &#039;screenio\&#039;. If you referenced any of these files in your existing code, you may need to update those references. We have generated this brconfig file of substitution statements to aid in this process. To use it simply add &#039;include screenio\screenio.sys&#039; to your brconfig.sys file.&lt;br /&gt;
       &lt;br /&gt;
WARNING: If any of the following substitution statements conflict with one of your file names you will not be able to use them. Carefully inspect these files to ensure they do not conflict with the names of any of your data files. If they do, you will not be able to use the substitution statements because they will affect your data files as well as your program name references. You will have to remove those lines from this file before using this file, and manually fix all the references in your existing code to any programs who&#039;s names conflict with your data files.&lt;br /&gt;
          &lt;br /&gt;
If you have any questions about this process, contact Gabriel Bakker at gabriel.bakker@gmail.com.&lt;br /&gt;
&lt;br /&gt;
== Future Changes ==&lt;br /&gt;
A partial list of future changes for ScreenIO has been added here. If any of you have a feature in mind that you&#039;d like to see and its not already listed here, feel free to add it. I will remove the features from the list as they are implemented in ScreenIO.&lt;br /&gt;
&lt;br /&gt;
=== New Future Change Requests ===&lt;br /&gt;
All currently requested features have been implemented. If you have a feature in mind you&#039;d like to see, feel free to post it here, and also please notify gabriel.bakker@gmail.com. When I have finished implementing the feature, i&#039;ll remove it from the list that you make here.&lt;br /&gt;
&lt;br /&gt;
*Add your Feature&lt;br /&gt;
*Requests Here&lt;br /&gt;
&lt;br /&gt;
=== Completed Future Change Requests ===&lt;br /&gt;
&lt;br /&gt;
The following list of change requests has been completed.&lt;br /&gt;
&lt;br /&gt;
*Additional Parameters in fnfm for Interacting with Screens, that get passed both in and out of your new screen.&lt;br /&gt;
*Non-Data Screens - the ability to call fnfm with your own mat F$ and mat F and have it work with your passed in data instead of automatically reading and writing from your data file.&lt;br /&gt;
*True Numeric Fields in Listviews supported with BR 4.2&lt;br /&gt;
*Numeric Fields on regular Text Box Controls&lt;br /&gt;
*Mainloop event to support custom keys&lt;br /&gt;
*Error Handling Improvement&lt;br /&gt;
*Animated &amp;quot;Loading Icon&amp;quot; for populating Large Listviews&lt;br /&gt;
*Group Movement/Alignment of controls&lt;br /&gt;
*Copy and Paste of Controls from one screen to another screen&lt;br /&gt;
*Group Copy and Paste of Controls&lt;br /&gt;
*ScreenIO Helper Libraries in a special folder&lt;br /&gt;
*ScreenIO itself in a special folder&lt;br /&gt;
*Add the &amp;quot;-d&amp;quot; option to the ScreenIO Screenfld file to keep it from growing huge after some time&lt;br /&gt;
*Additional Field level Properties in Screenflds for Programmers to use for things&lt;br /&gt;
*Support for TIMEOUT and WAIT in BR - Perhaps these should be events as well&lt;br /&gt;
*Advanced Filtering of a Listview - using the proper index to make it run faster&lt;br /&gt;
&lt;br /&gt;
[[Category:Utilities_Third_Party]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=FileIO_Library&amp;diff=3449</id>
		<title>FileIO Library</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=FileIO_Library&amp;diff=3449"/>
		<updated>2013-06-19T03:08:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;At the April 2006 [[BRGroup Conference]], [[User:Gabriel|Gabriel]] spoke to many of us about a new revolution in BR &#039;&#039;&#039;FileIO&#039;&#039;&#039; management. This topic generated so much interest that he was asked to present it again at the Fall Conference. There were also many suggestions for improvements to the library.&lt;br /&gt;
&lt;br /&gt;
The FileIO Library began as a project to find a way to reduce the headache associated with making changes to your data files. In my experiences working for [[BRC]], I had to make a change to the commun file, a data file that stores information about communication with EDI VANs. I added some new fields, and removed a couple of old fields, and then I began searching through the BRC program suite to find and modify each program that referenced this data file in order to update it with the proper new form statement. This task quickly became daunting as I noticed that out of BRC’s program suite of over 600 programs, more then 1/3rd of them referenced the commun file. With 223 programs to modify, the task was given up as hopeless and tabled indefinitely.&lt;br /&gt;
&lt;br /&gt;
I am happy to announce that we have solved this problem. When I have to make a change to a data file layout for my customers today, I can complete the task in under 1 minute, and none, not one single one of my programs needs to be changed in order to still work with the new file layout. In fact, I don’t even have to update my customer’s data files, as the FileIO library takes care of this for me as well.&lt;br /&gt;
&lt;br /&gt;
The trick is to define your file layouts in an ASCII text file layout file that I will tell you about in a minute. The FileIO Library will actually parse through your file layouts, and it will instruct your programs how to read the data file, so that you don’t have to. It will also automatically detect when you make changes to the file layout, and it will update your customer’s data files on the fly to make sure they have the latest version. Finally, it even contains a DataCrawler that you can use to examine the contents of any of your BR data files in a raw format.&lt;br /&gt;
&lt;br /&gt;
[[FileIO 2]] Improves upon FileIO in many ways. For information on FileIO 2, see the [[FileIO 2]] page.&lt;br /&gt;
&lt;br /&gt;
For more information about the FileIO Library visit the [http://www.sageax.com/products/fileio-library/ Sage AX Website]&lt;br /&gt;
&lt;br /&gt;
To download the latest copy of FileIO, click [http://www.sageax.com/downloads/FileIO.zip here.]&lt;br /&gt;
&lt;br /&gt;
== The Method ==&lt;br /&gt;
I have created a file IO library that parses a formatted text file layout and uses this information to structure the opening and initializing of the reading of a file “object”. The word object here is used to refer to all the data in a given record in one of your files. This library is easy to use, and provided you follow some simple standards, it will simplify your lives immensely.&lt;br /&gt;
&lt;br /&gt;
=== File Object Arrays ===&lt;br /&gt;
&lt;br /&gt;
First, in your program you must create two matrices to store the file information. If we are dealing with the Color File these would be MAT COLOR$ and MAT COLOR. One will store all the string information about a color, and the other will store all the numeric data. Our working example will involve two files: a Color File and a Color Category File. You should dimension these to:&lt;br /&gt;
&lt;br /&gt;
  01030    DIM color$(1)*255,color(1)&lt;br /&gt;
  01040    DIM colorcat$(1)*255,colorcat(1)&lt;br /&gt;
&lt;br /&gt;
=== Forms Array ===&lt;br /&gt;
&lt;br /&gt;
You will also need a variable to store the form statement associated with reading the files. This form statement will be dynamically generated whenever a new file is opened. It will say: &lt;br /&gt;
&lt;br /&gt;
  01020    DIM form$(1)*255&lt;br /&gt;
&lt;br /&gt;
=== Library Linkage ===&lt;br /&gt;
&lt;br /&gt;
You will also need the library call:&lt;br /&gt;
&lt;br /&gt;
  02020 library &amp;quot;fileio.br&amp;quot;: fnopenfile, fnreaddescription$&lt;br /&gt;
&lt;br /&gt;
=== fnOpen Function ===&lt;br /&gt;
&lt;br /&gt;
Now, a simple function placed into all your files will simplify one aspect of this. Because BR libraries do not share variables with the programs they are called from, we will need to execute a simple proc file whenever we open a file to set the names of all our variables after we return. Create an FnOpen that calls the library version and runs the proc file when we are done. Notice the $$$ at the end of the procfile name. This will tell the procfile to self-destruct after execution. Since this procfile is used simply to return variable information back from the library to the main program, we don’t need it sitting around collecting dust.&lt;br /&gt;
&lt;br /&gt;
  99010  OPEN: ! ***** Function To Call Library Openfile And Generate Subs&lt;br /&gt;
  99020     def Fnopen(Filename$*255, Mat F$, Mat F, Mat Form$; Inputonly, Keynum, Dont_Sort_Subs, Path$*255, Mat Descr$, Mat Field_Widths)&lt;br /&gt;
  99030        dim _FileIOSubs$(1)*800&lt;br /&gt;
  99040        let Fnopen=Fnopenfile(Filename$, Mat F$, Mat F, Mat Form$, Inputonly, Keynum, Dont_Sort_Subs, Path$, Mat Descr$, Mat Field_Widths, Mat _FileIOSubs$)&lt;br /&gt;
  99050        for Index=1 to udim(mat _FileIOSubs$) : execute (_FileIOSubs$(Index)) : next Index&lt;br /&gt;
  99060     fnend&lt;br /&gt;
&lt;br /&gt;
=== Using FileIO in Your Programs ===&lt;br /&gt;
&lt;br /&gt;
Now you are ready to process files. You simply open the file by saying:&lt;br /&gt;
&lt;br /&gt;
  04020    let colorfile=fnopen(&amp;quot;color&amp;quot;,mat color$,mat color,mat form$)&lt;br /&gt;
  04030    let colorcatfile=fnopen(&amp;quot;colorcat&amp;quot;,mat colorcat$,mat colorcat,mat form$,1)&lt;br /&gt;
&lt;br /&gt;
These statements tell the File Library to look in the filelay folder to find the file layout for the Color File, and read it to find out what the Color File looks like. Then Open the Color File, and set MAT COLOR$ and MAT COLOR to the correct size to hold an entire color record. Finally, it will define several variables that we can use as pointers in these arrays to read the data we want to see, and it will place the file handle into a variable called colorfile.&lt;br /&gt;
&lt;br /&gt;
The second line above will do the same thing to the routing file, except the 1 parameter tells the function to open readonly. Because of the extra function we inserted into our program earlier, the subscripts array will be executed, creating the subscripts in memory, and the pointers (subscripts) will be set in the returned program. So, if I had a file layout such as the following:&lt;br /&gt;
&lt;br /&gt;
  color.dat, CO_, 1&lt;br /&gt;
  color.key, CODE&lt;br /&gt;
  recl=127&lt;br /&gt;
  ===================================================&lt;br /&gt;
  CODE$,          Color Code,                  C    6&lt;br /&gt;
  NAME$,          English Name for Color,      V   30&lt;br /&gt;
  CATEGORY$,      General Category of Color,   C    6&lt;br /&gt;
  HTML$,          HTML Code for the Color,     C    6&lt;br /&gt;
&lt;br /&gt;
Then the functions would do the same thing as the following individual lines of code (assuming the next available file handle was 5):&lt;br /&gt;
&lt;br /&gt;
  DIM FORM$(5)*255&lt;br /&gt;
  DIM COLOR$(9)*255, COLOR(1)&lt;br /&gt;
  OPEN #5: “Name=color.dat, kfname=color.key”,internal,outin,keyed&lt;br /&gt;
  LET FORM$(5)=”form C 6,V 30,V 6,C 6”&lt;br /&gt;
  LET FORM$(5)=CFORM$(FORM$(5))&lt;br /&gt;
  LET COLORFILE=5&lt;br /&gt;
  CO_CODE=1&lt;br /&gt;
  CO_NAME=2&lt;br /&gt;
  CO_CATEGORY=3&lt;br /&gt;
  CO_HTML=4&lt;br /&gt;
&lt;br /&gt;
Now we can read the file:&lt;br /&gt;
&lt;br /&gt;
  30120    read #colorfile, using form$(colorfile) : mat color$, mat color eof Ignore&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
and use the data:&lt;br /&gt;
&lt;br /&gt;
  30180    LET ColorCode$=color$(co_Code) !:&lt;br /&gt;
           LET ColorName$=color$(co_Name)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The data is used by referencing the file array, with the subscript name, so the color’s description becomes color$(co_Name).&lt;br /&gt;
&lt;br /&gt;
In the old days, if we wanted to change the file layout of our file, all of the programs that used that file would have to be changed one at a time to use the new file layout. Also, if the order of the fields changed, then all the programs would have to also be changed to use the new fields.&lt;br /&gt;
&lt;br /&gt;
But now, using this function, we can change the file layout all we want. If we later want to insert a field into the file layout before color name, I won’t have to look at this program again; this program will just work fine, because the library tells it which fields to use.&lt;br /&gt;
&lt;br /&gt;
Also, the code is easier to read and maintain.&lt;br /&gt;
&lt;br /&gt;
=== Example ===&lt;br /&gt;
The whole thing looks like this:&lt;br /&gt;
&lt;br /&gt;
  01025    ! Dimension the Arrays&lt;br /&gt;
  01030    DIM color$(1)*255,color(1)&lt;br /&gt;
  01040    DIM colorcat$(1)*255,colorcat(1)&lt;br /&gt;
  01050    DIM form$(1)*255&lt;br /&gt;
  02000 !&lt;br /&gt;
  02020 library &amp;quot;fileio.br&amp;quot;: fnopenfile, fnreaddescription$&lt;br /&gt;
  04020    let colorfile=fnopen(&amp;quot;color&amp;quot;,mat color$,mat color,mat form$) ! Open the file&lt;br /&gt;
  05000 ! &lt;br /&gt;
  30120    read #colorfile, using form$(colorfile) : mat color$, mat color eof Ignore ! Read the file&lt;br /&gt;
  30180    LET ColorCode$=color$(co_Code) !:&lt;br /&gt;
           LET ColorName$=color$(co_Name) ! Use the data by referincing it in the file arrays&lt;br /&gt;
  80000 !&lt;br /&gt;
  90000 ! Every program using fileio needs the following code&lt;br /&gt;
  99010  OPEN: ! ***** Function To Call Library Openfile And Generate Subs&lt;br /&gt;
  99020     def Fnopen(Filename$*255, Mat F$, Mat F, Mat Form$; Inputonly, Keynum, Dont_Sort_Subs, Path$*255, Mat Descr$, Mat Field_Widths)&lt;br /&gt;
  99030        dim _FileIOSubs$(1)*800&lt;br /&gt;
  99040        let Fnopen=Fnopenfile(Filename$, Mat F$, Mat F, Mat Form$, Inputonly, Keynum, Dont_Sort_Subs, Path$, Mat Descr$, Mat Field_Widths, Mat _FileIOSubs$)&lt;br /&gt;
  99050        for Index=1 to udim(mat _FileIOSubs$) : execute (_FileIOSubs$(Index)) : next Index&lt;br /&gt;
  99060     fnend&lt;br /&gt;
&lt;br /&gt;
== File Layouts ==&lt;br /&gt;
Now let me demonstrate the anatomy of a properly formatted file layout. These should be placed in a subdirectory called filelay.&lt;br /&gt;
&lt;br /&gt;
  price.dat, PR_, 1&lt;br /&gt;
  price.key, FARM&lt;br /&gt;
  price.ky2, ITEM&lt;br /&gt;
  price.ky3, FARM/ITEM/GRADE&lt;br /&gt;
  recl=127&lt;br /&gt;
  ===================================================&lt;br /&gt;
  FARM$,          Farm Code (or blank),        C    4&lt;br /&gt;
  ITEM$,          Item Code,                   C    4&lt;br /&gt;
  GRADE$,         Quality,                     C    4&lt;br /&gt;
  X,              Empty,                       X   37&lt;br /&gt;
  PRICE,          Default Price,               BH 3.2&lt;br /&gt;
  COST,           Default Cost,                BH 3.2&lt;br /&gt;
  XOPRICE,        Default Christmas Price,     BH 3.2&lt;br /&gt;
  XOCOST,         Default Christmas Cost,      BH 3.2&lt;br /&gt;
  MOPRICE,        Default Mothers D Price,     BH 3.2&lt;br /&gt;
  MOCOST,         Default Mothers D Cost,      BH 3.2&lt;br /&gt;
  VOPRICE,        Default Valentine Price,     BH 3.2&lt;br /&gt;
  VOCOST,         Default Valentine Cost,      BH 3.2&lt;br /&gt;
  DESCRIPTION$,   Description of Price Rule,   C   30&lt;br /&gt;
 &lt;br /&gt;
The first line contains the name of the Farm File, a unique prefix to add to all your subscript index pointers, and the file version number. The subscript value is to ensure that the program knows the difference between the Farm File’s Farm Code, and the Route File’s Route Code. (One will be RT_CODE and the other is FM_CODE).  These are separated by a comma. Spacing does not matter, so adjust your spacing so that it looks nice.&lt;br /&gt;
&lt;br /&gt;
The Version number is used to determine when the data has changed, and an update needs to be made to your data file. Your file layouts should all start at version 0, and each time you want to make a change, you may increment this value by 1.&lt;br /&gt;
&lt;br /&gt;
If you look in the filelay folder, you will notice several files ending with a number. For example, you may see a color, a color.0, and a color.1 file. If you run the function and it can not find your data file (usually because this is a new file and it hasn’t been created yet), the function library will automatically create your file, based on the information you give in the first part of the file layout. Also, whenever you make changes to your file layout, the function library will automatically update the data files on disk for you. It does this by renaming the old file, creating a new one with the new version number, and then copying the data from the old one to the new one a record at a time.&lt;br /&gt;
&lt;br /&gt;
Any time it creates a file, or updates the file on disk, it creates a backup of the file layout. The first time you run a program that tries to read your new data file, it will create the data file for you and make a backup, and if the number in your file layout is 0, then it will create, for example, a filelay\price.0 file, a backup of your file layout that the library uses to figure out what has changed the next time you try to update the file.&lt;br /&gt;
&lt;br /&gt;
If you wish to make any changes to this data file, first you increment the version number, (in this case make the 0 into a 1). Then change the file layout all you want. You may rearrange fields, add new fields, add or remove keys, or change the record length.&lt;br /&gt;
&lt;br /&gt;
Each time you try to open a file with the library, it reads the file version number of the file on disk (using the BR version() function), and then it compares it to the version number in your file layout. If your file layout has a higher version number then your existing data file, then the library opens the backup of the file layout for the version of the data file that exists on disk. It makes a backup copy of the existing data file, and creates a new file with the proper version number. Then it reads your records one at a time, and copies all the data from the old file into the new file one field at a time. If a field is dropped from the file layout, that data gets lost. If fields are rearranged, the data is copied and saved in the new file in the new positions. If a new field is added, it starts out blank (or 0).&lt;br /&gt;
&lt;br /&gt;
The only step necessary for having your data files updated is to increment the version number every time you make a change to the file layout. You may make any changes you like to the file layouts, but do not change the names of your existing subscripts. If you change the subscript name, not only will all the programs that reference that subscript be broken, but additionally, the routine will not understand that you are changing the name. It will think you are dropping the old field and adding a new field and any data stored in this location will be lost when the file is updated.&lt;br /&gt;
&lt;br /&gt;
  price.dat, PR_, 1&lt;br /&gt;
&lt;br /&gt;
The second line contains the name of the first key, and a definition telling what the key is based on. These are separated by a comma. The key definition is made up of each of the subscript names in this file that form the keyfields for the file. When the library is called to open a file, if the file does not exist, or if it needs to be updated, a new one will be created. The function will read these subscript names that form your key definitions, and it will calculate the proper kps and kln values. Then the create routine will use this information to create the new keys.&lt;br /&gt;
&lt;br /&gt;
You notice the file can have as many keys as you want. The function will keep parsing key file names until it reaches the RECL= parameter. Remember it opens any OutIn files with all keys so that any changes you may make to the data stored on disk will be properly reflected in all the key files.&lt;br /&gt;
&lt;br /&gt;
Also, notice the third key is based on three different fields. These are separated by a “/”. It is important that you use a “/” to separate your keys when you are building a key out of more then one field, because the function uses this “/” to help it make the proper BR syntax for defining complex keyfields.&lt;br /&gt;
&lt;br /&gt;
The RECL= Parameter is also read and used whenever a new file is created or an old one is updated. It is also used to tell the function when to stop looking for key file names, and start looking for the rest of the data.&lt;br /&gt;
&lt;br /&gt;
  price.key, ITEM&lt;br /&gt;
  price.ky2, FARM&lt;br /&gt;
  price.ky3, ITEM/FARM/GRADE&lt;br /&gt;
  recl=127&lt;br /&gt;
&lt;br /&gt;
The next line in the file is skipped by the parsing routine, and its purpose is to make the file layouts more readable to a programmer.&lt;br /&gt;
&lt;br /&gt;
  ===================================================&lt;br /&gt;
&lt;br /&gt;
Following file layouts, we will discuss data elements. There are three parameters on each line, and you make one line for each field in your file. The first parameter is the subscript index prefix code that you will use in your program to refer to this data element. Place a $ at the end of the subscript name for all string elements. Don’t place anything at the end of the subscript name for numeric elements.&lt;br /&gt;
&lt;br /&gt;
The spaces are ignored, so you may include as many spaces as you wish to make the layout look good. However the file layout is designed to handle a maximum of 255 characters on each line, and a maximum of 80 characters for the Description names. Do not use tabs, however. For some reason, tabs confuse BR. The second parameter is the description. This description is for the benefit of the programmer, so when the programmer is reading the file layouts, (s)he can tell which field does what.&lt;br /&gt;
&lt;br /&gt;
The description is also used by the built in DataCrawler, a program that reads any of your data files and displays the entire contents in raw form in a listview. The Descriptions become the headings for each column in the listview. Imagine this as something that you would show to a programmer, or a highly technical user who needed to investigate a data error of some kind.&lt;br /&gt;
&lt;br /&gt;
The third parameter is the form statement, which is pretty straightforward. Any items with a form statement of type “X” will be ignored, except that the length will still be used to calculate the position on disk of all remaining fields in the record. The library will take X fields into consideration when building the form statement, but not at any other time.&lt;br /&gt;
&lt;br /&gt;
  FARM$,          Farm Code (or blank),        C    4&lt;br /&gt;
  ITEM$,          Item Code,                   C    4&lt;br /&gt;
  GRADE$,         Quality,                     C    4&lt;br /&gt;
  DUMMY,          Empty,                       X   37&lt;br /&gt;
  PRICE,          Default Price,               BH 3.2&lt;br /&gt;
  COST,           Default Cost,                BH 3.2&lt;br /&gt;
  XOPRICE,        Default Christmas Price,     BH 3.2&lt;br /&gt;
  XOCOST,         Default Christmas Cost,      BH 3.2&lt;br /&gt;
  MOPRICE,        Default Mothers D Price,     BH 3.2&lt;br /&gt;
  MOCOST,         Default Mothers D Cost,      BH 3.2&lt;br /&gt;
  VOPRICE,        Default Valentine Price,     BH 3.2&lt;br /&gt;
  VOCOST,         Default Valentine Cost,      BH 3.2&lt;br /&gt;
  DESCRIPTION$,   Description of Price Rule,   C   30&lt;br /&gt;
&lt;br /&gt;
And that’s all there is to it.&lt;br /&gt;
&lt;br /&gt;
== The Library (Function Reference) ==&lt;br /&gt;
The library includes a number of useful functions. I hope you find these to be as useful for you as I have found them to be for me.&lt;br /&gt;
&lt;br /&gt;
=== fnSettings (Global Settings Code) ===&lt;br /&gt;
&lt;br /&gt;
The newest version of the FileIO library supports some features that require you to specify Global Settings values. These are done by modifying the contents of the fnSettings routine at the beginning of the fileIO library.&lt;br /&gt;
&lt;br /&gt;
  01010  SETTINGS: ! ***** Set Global Defaults For The Library Here&lt;br /&gt;
  01020     def Fnsettings(&amp;amp;Defaultfilelayoutpath$;&amp;amp;Promptonfilecreate,&amp;amp;Createlogfile,&amp;amp;EnforceDupkeys,&amp;amp;StartFileNumber)&lt;br /&gt;
  01030        let EnforceDupkeys=1                  ! Enforce that key number 1 is unique key&lt;br /&gt;
  01040        let Defaultfilelayoutpath$=&amp;quot;filelay\&amp;quot; ! Path To Your File Layouts&lt;br /&gt;
  01050        let Promptonfilecreate=1              ! Ask User Before Creating New Files&lt;br /&gt;
  01060        let Createlogfile=0                   ! Create the logfile&lt;br /&gt;
  01070        let StartFileNumber=1                 ! File IO will use file numbers above this number&lt;br /&gt;
  01080        let CheckIndex=0                      ! Automatically Update Indexes &lt;br /&gt;
  01080     fnend&lt;br /&gt;
&lt;br /&gt;
==== EnforceDupkeys ====&lt;br /&gt;
&lt;br /&gt;
Turn on the EnforceDupkeys option to force that the first key listed in your file layouts is a unique key. FileIO will generate the standard BR error for Dupkeys when attempting to create indexes if it is not unique.&lt;br /&gt;
&lt;br /&gt;
==== DefaultFileLayoutPath ====&lt;br /&gt;
&lt;br /&gt;
Use the DefaultFileLayoutPath option to specify the path from your programs to your file layout folder. The default is &amp;quot;filelay\&amp;quot;. Use this setting if you want to place your file layouts in another folder from the default.&lt;br /&gt;
&lt;br /&gt;
==== PromptOnFileCreate ====&lt;br /&gt;
&lt;br /&gt;
Use the PromptOnFileCreate setting to cause FileIO to put up a message box whenever its attempting to create a new file. This happens during the automatic update procedure, as well as during any attempt to access a file that does not exist. This setting should be turned off in your live system, and only turned on for development purposes. If you use the message box to cancel creating of the new file, then the file is not created, and fileIO or your application will most likely give an error when you attempt to actually access the new file.&lt;br /&gt;
&lt;br /&gt;
It can be useful during development to make sure that you don&#039;t accidentally create the wrong files, due to an incorrectly specified path or a typeo in the filename in the layout file. However, in a live system, these things have already been tested, and you generally want the default behavior, because you don&#039;t want your users to have the ability to cancel the normal operation of FileIO.&lt;br /&gt;
&lt;br /&gt;
==== CreateLogFile ====&lt;br /&gt;
&lt;br /&gt;
Use this option to specify weather or not to use the FileIO log file. If it is turned on, a log file called FileIO.log in the current directory is created with entries listing all attempts to open a file, automatically update one, or automatically update your indexes.&lt;br /&gt;
&lt;br /&gt;
==== StartFileNumber ====&lt;br /&gt;
&lt;br /&gt;
Use this option to set the starting file number that the fnGetFileNumber and the fnOpen functions use to search for available file numbers. This is so that if you have certian reserved file numbers in your code, you can make sure that FileIO will not use those reserved file numbers, causing a conflict with your already existing programs. The default is 1, which is fine if your software does not have any reserved file numbers.&lt;br /&gt;
&lt;br /&gt;
==== CheckIndex ====&lt;br /&gt;
&lt;br /&gt;
This function is used for Partial FileIO Implementations. If all your software uses FileIO then all of your indexes are kept automatically up to date by the FileIO library and BR&#039;s internal file processing systems. However, if some of programs do not use FileIO, and you use the FileIO library to add a new index file that those other programs do not know about, then its possible for the additional index file to become out of date when the master file is updated by your other programs.&lt;br /&gt;
&lt;br /&gt;
Use this setting to cause FileIO to check the DateTime stamp on all your index files when opening a new file, and automatically update any indexes that may have potentially gotten out of date from other programs.&lt;br /&gt;
&lt;br /&gt;
This option slows down the processing of the fnOpen function, particularly when running under client server over the internet. If you know that every program in your application suite uses FileIO, and that any programs that do not use FileIO still properly update all the indexes that your data file uses, then you can safely leave this setting turned off, and take advantage of a significant speed increase when opening a lot of files using the fileIO system.&lt;br /&gt;
&lt;br /&gt;
=== fnOpenFile ===&lt;br /&gt;
The primary function opens a file, and it’s used like so:&lt;br /&gt;
&lt;br /&gt;
  FNOPENFILE(FILENAME$,MAT F$,MAT F,MAT FORM$;INPUTONLY,KEYNUM,DONT_SORT_SUBS,&lt;br /&gt;
    PATH$,MAT DESCR$,MAT FIELDWIDTHS,SUPRESS_PROMPT)&lt;br /&gt;
  &lt;br /&gt;
  FILENAME$ - The filename of the file layout for the file you’re reading.&lt;br /&gt;
  MAT F$ - The array that will be used to hold the string data for the file.&lt;br /&gt;
  MAT F – The array that will hold the numeric data for the file.&lt;br /&gt;
  MAT FORM$ - An array of form statements.&lt;br /&gt;
  INPUTONLY – 1 means open for input only. 0 means open for OutIn and open every&lt;br /&gt;
    key file associated with the given data file (this is because all key files&lt;br /&gt;
    need to be open for the keys to be updated on an output) (defaults to 0).&lt;br /&gt;
  KEYNUM – This tells the function of which key to return the file handle (defaults to 1).&lt;br /&gt;
  DONT_SORT_SUBS – The function by default will sort the string and numeric subs in order&lt;br /&gt;
    to allow for reading the data into an array, and this parameter would turn this&lt;br /&gt;
    functionality off. However, if you are trying to read your data without reading&lt;br /&gt;
    it into an array, you are missing the point. You should leave this option turned&lt;br /&gt;
    off (0). This is a totally unsupported feature, and should always be set to 0, if&lt;br /&gt;
    it is specified at all.&lt;br /&gt;
  PATH$ - The path to your data files. This optional parameter can be passed in by the&lt;br /&gt;
    calling function. It is appended to the beginning of the paths given in the file&lt;br /&gt;
    layout files. It is useful when your data files can be in different locations&lt;br /&gt;
    depending on the state of your program.&lt;br /&gt;
  MAT DESCR$ - This optional parameter provides a way to read the description for&lt;br /&gt;
    each field from the original file layout. If the parameter is not provided, no&lt;br /&gt;
    description data will be returned. &lt;br /&gt;
  MAT FIELDWIDTHS – This optional parameter will return an array of the calculated&lt;br /&gt;
    display field widths. This number will always be at least long enough to contain&lt;br /&gt;
    the data for this field.&lt;br /&gt;
  SUPRESS_PROMPT - This optional parameter can be used to supress the prompt normally&lt;br /&gt;
    given when fileIO creates a file. It can have three values. A value of 0, the default,&lt;br /&gt;
    uses the setting stored in your FileIO fnSettings routine to determine weather or not&lt;br /&gt;
    to prompt on Creation of a new file. A nonzero value always supresses the prompt. A&lt;br /&gt;
    value of 1 indicates never to create a file if the file doesn&#039;t exist. A value of 2&lt;br /&gt;
    automatically creates the file if the file doesn&#039;t exist.&lt;br /&gt;
&lt;br /&gt;
* When using fnOpenFile, you really want to call your local function FnOpen, which in turn calls fnOpenFile for you.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
  Let FFILE=FNOPENFILE(“FARM”,MAT FARM$,MAT FARM,MAT FORM$,0,2)&lt;br /&gt;
  Let RFILE=FNOPENFILE(“ROUTE”,MAT ROUTE$,MAT ROUTE,MAT FORM$,1,3)&lt;br /&gt;
  Let CFILE=FNOPENFILE(“CUSTOMER”,MAT CUSTOMER$,MAT CUSTOMER,MAT FORM$)&lt;br /&gt;
&lt;br /&gt;
assuming:&lt;br /&gt;
  farm.dat has 3 keys: farm.ky1, farm.ky2, farm.ky3&lt;br /&gt;
  route.dat has 4 keys: route.ky1 … route.ky4&lt;br /&gt;
  customer.dat has 2 keys: customer.ky1, customer.ky2&lt;br /&gt;
&lt;br /&gt;
This will perform the following opens and set the following variables:&lt;br /&gt;
&lt;br /&gt;
  OPEN #1: “Name=Farm.Dat, kfname=farm.ky2”,internal,outin,keyed&lt;br /&gt;
  OPEN #2: “Name=Farm.Dat, kfname=farm.ky1”,internal,outin,keyed&lt;br /&gt;
  OPEN #3: “Name=Farm.Dat, kfname=farm.ky3”,internal,outin,keyed&lt;br /&gt;
  OPEN #4: “Name=Route.Dat, kfname=route.ky3”,internal,input,keyed&lt;br /&gt;
  OPEN #5: “Name=Customer.Dat,kfname=customer.ky1”,internal,outin,keyed&lt;br /&gt;
  OPEN #6: “Name=Customer.Dat,kfname=customer.ky2”,internal,outin,keyed&lt;br /&gt;
  LET FFILE=1&lt;br /&gt;
  LET RFILE=4&lt;br /&gt;
  LET CFILE=5&lt;br /&gt;
&lt;br /&gt;
This will also resize the arrays, set the form statement, and create all the subscripts to make reading and writing clear and simple, as in the above example. The KEYNUM parameter is where you list the key file you would like to use for input and output. The extra keys are opened as a courtesy to you to ensure that all keys get updated properly when the file is changed.&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
  DIM FORM$(1),PRICE$(1)*255,PRICE(1),&lt;br /&gt;
  DIM DESCRIPTION$(1)*255,FIELDWIDTHS(1)&lt;br /&gt;
&lt;br /&gt;
  Let PRICEFILE=FNOPENFILE(“PRICE”,MAT PRICE$,MAT PRICE,MAT FORM$,0,2,0,MAT DESCRIPTION$)&lt;br /&gt;
&lt;br /&gt;
Assuming the Price File layout (filelay\price) contains:&lt;br /&gt;
&lt;br /&gt;
  price.dat, PR_, 1&lt;br /&gt;
  price.key, FARM&lt;br /&gt;
  price.ky2, ITEM&lt;br /&gt;
  price.ky3, FARM/ITEM/GRADE&lt;br /&gt;
  recl=127&lt;br /&gt;
  ===================================================&lt;br /&gt;
  FARM$,          Farm Code (or blank),        C    4&lt;br /&gt;
  ITEM$,          Item Code,                   C    4&lt;br /&gt;
  GRADE$,         Quality,                     C    4&lt;br /&gt;
  DUMMY,          Empty,                       X   37&lt;br /&gt;
  PRICE,          Default Price,               BH 3.2&lt;br /&gt;
  COST,           Default Cost,                BH 3.2&lt;br /&gt;
  XOPRICE,        Default Christmas Price,     BH 3.2&lt;br /&gt;
  XOCOST,         Default Christmas Cost,      BH 3.2&lt;br /&gt;
  MOPRICE,        Default Mothers D Price,     BH 3.2&lt;br /&gt;
  MOCOST,         Default Mothers D Cost,      BH 3.2&lt;br /&gt;
  VOPRICE,        Default Valentine Price,     BH 3.2&lt;br /&gt;
  VOCOST,         Default Valentine Cost,      BH 3.2&lt;br /&gt;
  DESCRIPTION$,   Description of Price Rule,   C   30&lt;br /&gt;
 &lt;br /&gt;
This will perform the following opens and set the following variables:&lt;br /&gt;
&lt;br /&gt;
  OPEN #1: “Name=Price.Dat, kfname=Price.ky2”,internal,outin,keyed&lt;br /&gt;
  OPEN #2: “Name=Price.Dat, kfname=Price.ky1”,internal,outin,keyed&lt;br /&gt;
  OPEN #3: “Name=Price.Dat, kfname=Price.ky3”,internal,outin,keyed&lt;br /&gt;
  let PRICEFILE=1&lt;br /&gt;
  let PR_FARM=1&lt;br /&gt;
  let PR_ITEM=2&lt;br /&gt;
  let PR_GRADE=3&lt;br /&gt;
  let PR_DESCR=4&lt;br /&gt;
  let PR_PRICE=1&lt;br /&gt;
  let PR_COST=2&lt;br /&gt;
  let PR_XOPRICE=3&lt;br /&gt;
  let PR_XOCOST=4&lt;br /&gt;
  let PR_MOPRICE=5&lt;br /&gt;
  let PR_MOCOST=6&lt;br /&gt;
  let PR_VOPRICE=7&lt;br /&gt;
  let PR_VOCOST=8&lt;br /&gt;
  MAT FORM$(1)&lt;br /&gt;
  MAT PRICE$(4)&lt;br /&gt;
  MAT PRICE(8)&lt;br /&gt;
  MAT DESCRIPTION$(12)&lt;br /&gt;
  MAT FIELDWIDTHS(12)&lt;br /&gt;
  let FORM$(1)=CFORM$(”form C 4,C 4,C 4,POS 74,C 30,POS 50,BH 3.2,BH 3.2,BH 3.2,BH 3.2,BH 3.2,BH 3.2,BH 3.2,BH 3.2”)&lt;br /&gt;
  let Description$(1)= “Farm Code (or blank)”&lt;br /&gt;
  let Description$(2) = “Item Code”&lt;br /&gt;
  let Description$(3) = “Quality”&lt;br /&gt;
  let Description$(4) = “Description of Price Rule”&lt;br /&gt;
  let Description$(5) = “Default Price”&lt;br /&gt;
  let Description$(6) = “Default Cost”&lt;br /&gt;
  let Description$(7) = “Default Christmas Price”&lt;br /&gt;
  let Description$(8) = “Default Christmas Cost”&lt;br /&gt;
  let Description$(9) = “Default Mothers D Price”&lt;br /&gt;
  let Description$(10) = “Default Mothers D Cost”&lt;br /&gt;
  let Description$(11) = “Default Valentine Price”&lt;br /&gt;
  let Description$(12) = “Default Valentine Cost”&lt;br /&gt;
  let FieldWidths(1) = 4&lt;br /&gt;
  let FieldWidths(2) = 4&lt;br /&gt;
  let FieldWidths(3) = 4&lt;br /&gt;
  let FieldWidths(4) = 30&lt;br /&gt;
  let FieldWidths(5) = 8&lt;br /&gt;
  let FieldWidths(6) = 8&lt;br /&gt;
  let FieldWidths(7) = 8&lt;br /&gt;
  let FieldWidths(8) = 8&lt;br /&gt;
  let FieldWidths(9) = 8&lt;br /&gt;
  let FieldWidths(10) = 8&lt;br /&gt;
  let FieldWidths(11) = 8&lt;br /&gt;
  let FieldWidths(12) = 8&lt;br /&gt;
  &lt;br /&gt;
&lt;br /&gt;
There are a few things I’d like to point out about the example above. First, you will notice that the form statement jumps around to put all the strings first, and then the numbers last. This is why it has a “POS 74, C 30,POS 50”. Then notice that the subscripts for the string variables are 1 .. 4, and the subscripts for the numbers are 1 .. 8. Finally, the order of the Description and FieldWidth fields also match the sorted positioning of the Form Statement.&lt;br /&gt;
&lt;br /&gt;
The reason that we sort our form statements is so that BR will allow us to read the file into arrays by saying:&lt;br /&gt;
&lt;br /&gt;
  Read #pricefile, using form$(pricefile) : mat price$, mat price&lt;br /&gt;
&lt;br /&gt;
Without resorting, the above statement would give a conversion error as BR attempted to put the PR_PRICE field inside mat price$(4). However, because we have reordered the form statement, we are able to read them safely into two arrays, and then we will be able to use the values without caring what position they are in the file, by simply saying PRICE$(PR_DESCRIPTION) when we want the description, and PRICE(PR_PRICE) when we want the pr_Price field.&lt;br /&gt;
&lt;br /&gt;
Another thing you may notice about the above example is that it gives the calculated display length for the numeric fields as 8, when on the disk (and in the file layout) they are listed as BH 3.2. The reason for this is the program looks at the BH 3, and figures that a number that takes up 3 bytes on disk has a potential maximum size of 256**3 or 16,777,216, and therefore will need up to 8 characters of screen display space to view. &lt;br /&gt;
&lt;br /&gt;
Finally, note that any field with a form statement of X is ignored by the library, except that the blank space is used when building the FORM statement.&lt;br /&gt;
&lt;br /&gt;
FnOpenFile and FnOpen have been improved to pass the subscripts back in an array instead of a proc file, which is much faster, and also not as prone to causing file sharing errors.&lt;br /&gt;
&lt;br /&gt;
=== fnCloseFile ===&lt;br /&gt;
This function will close the specified filenumber and all keys that were opened with the file. You should use it only for files that were opened using the library for OutIn. The purpose of this function is to facilitate the closing of the extra keys that are opened when you open a file for OutIn with the library. You must give the function the name of the file layout. It uses this information to determine how many keys were opened, and how many it must therefore close. Then it basically starts at the file number you gave it, and closes the next X files that were opened with the same file name as this, where X is the number of keys associated with this file.&lt;br /&gt;
&lt;br /&gt;
The syntax is:&lt;br /&gt;
&lt;br /&gt;
  FNCLOSEFILE(filenumber,filelay$;path$)&lt;br /&gt;
&lt;br /&gt;
  FileNumber – The filenumber of the file you are trying to close.&lt;br /&gt;
  FileLay$ - The name of the file layout for this file. This is used to determine&lt;br /&gt;
    how many keys the file would have been opened with and therefore how many we&lt;br /&gt;
    now need to close.&lt;br /&gt;
  Path$ - Optional Alternate Path. Use to close files that were opened using the open file&#039;s optional alternate path parameter.&lt;br /&gt;
&lt;br /&gt;
=== fnMakeSubProc ===&lt;br /&gt;
The standard FNOpenFile routine opens a file and sets several values, and also passes back the subscripts to the calling program. The fnMakeSubProc$ routine passes back the subs without actually opening the file. This is useful when a file record is passed as arrays into a library function in another program, or when you chained to another program and you need to know how to reach the data in the arrays without actually reopening the file.&lt;br /&gt;
&lt;br /&gt;
  FNMakeSubProc(filelay$;mat Subscripts$) - Returns Just the Subscripts of the given file.&lt;br /&gt;
&lt;br /&gt;
  FileLay$ - The name of the file layout from which to read the subscripts.&lt;br /&gt;
  mat Subscripts$ - If you give this optional array, fnMakeSubProc passes the&lt;br /&gt;
    subscripts back in this array rather then in the subs.$$$ file. This is&lt;br /&gt;
    much faster and helps avoid sharing conflicts.&lt;br /&gt;
&lt;br /&gt;
When this routine returns, you can set the subscripts in your program by executing every element of the Subscripts$ array in a for/next loop.&lt;br /&gt;
&lt;br /&gt;
If you did not pass in a subscripts array, then the old subs.$$$ file is created for backwards compatability. If you proc that file, the proper subscripts will be set.&lt;br /&gt;
&lt;br /&gt;
=== fnReadLayoutArrays ===&lt;br /&gt;
This function reads the fields in a file layout into arrays. You call it like the following&lt;br /&gt;
&lt;br /&gt;
  fnReadLayoutArrays(filelay$,&amp;amp;prefix$;mat SSubs$, mat NSubs$, mat SSpec$, mat NSpec$,&lt;br /&gt;
    mat SDescription$, mat NDescription$,Mat Spos,Mat Npos,)&lt;br /&gt;
  &lt;br /&gt;
  filelay$ - the name of the layout to read&lt;br /&gt;
  prefix$ - the return value for the prefix for the file&lt;br /&gt;
  mat SSubs$ - the return value for all the string subscripts in the layout&lt;br /&gt;
  mat NSubs$ - the return value for the numeric subscripts in the layout&lt;br /&gt;
  mat SSpec$ - the return value for the string fields specs&lt;br /&gt;
  mat NSpec$ - the return value for the numeric fields specs&lt;br /&gt;
  mat SDescription$ - the return value for the Descriptions of the String Specs&lt;br /&gt;
  mat NDescription$ - the return value for the Descriptions of the Numeric Specs&lt;br /&gt;
  mat SPos - the return value for the starting positions of the String Specs&lt;br /&gt;
  mat NPos - the return value for the starting positions of the Numeric Specs&lt;br /&gt;
&lt;br /&gt;
This function call would read the fields from the layout in filelay$, and it would return the prefix to prefix$. The Subs would be returned in mat SSubs$ and mat NSubs$. The Spec statements are returned in mat SSpec$ and mat NSpec$ and the Descriptions are returned in mat SDescription$ and mat NDescription$. The start positions on disk of each element are returned in mat SPos and mat NPos. All the arrays are optional. If you don’t pass them the information they supposed to record is simply not returned. &lt;br /&gt;
&lt;br /&gt;
=== fnReadLayoutHeader ===&lt;br /&gt;
This function reads the header for a given file layout.&lt;br /&gt;
&lt;br /&gt;
  FnReadLayoutHeader(Layoutname$*255;&amp;amp;Filename$,Mat Keys$,Mat KeyDescription$)&lt;br /&gt;
  &lt;br /&gt;
  LayoutName$ - Name of the layout to read&lt;br /&gt;
  Filename$ - The file name read from the layout&lt;br /&gt;
  Mat Keys$ - Array to be populated with the list of keys for the file&lt;br /&gt;
  Mat KeyDescription$ - Key Description String returned from the file&lt;br /&gt;
&lt;br /&gt;
=== fnReadEntireLayout ===&lt;br /&gt;
This function reads the entire layout by calling fnReadLayoutHeader and fnReadLayoutArrays.&lt;br /&gt;
&lt;br /&gt;
  FnReadEntireLayout(Layoutname$*255;&amp;amp;Filename$,&amp;amp;Prefix$,Mat Keys$,Mat KeyDescription$,&lt;br /&gt;
    Mat Ssubs$,Mat Nsubs$,Mat Sspec$,Mat Nspec$,Mat Sdescription$,Mat Ndescription$,&lt;br /&gt;
    Mat Spos,Mat Npos)&lt;br /&gt;
  &lt;br /&gt;
  LayoutName$ - Name of the layout to read&lt;br /&gt;
  Filename$ - The file name read from the layout&lt;br /&gt;
  prefix$ - the return value for the prefix for the file&lt;br /&gt;
  Mat Keys$ - Array to be populated with the list of keys for the file&lt;br /&gt;
  Mat KeyDescription$ - Key Description String returned from the file&lt;br /&gt;
  mat SSubs$ - the return value for all the string subscripts in the layout&lt;br /&gt;
  mat NSubs$ - the return value for the numeric subscripts in the layout&lt;br /&gt;
  mat SSpec$ - the return value for the string fields specs&lt;br /&gt;
  mat NSpec$ - the return value for the numeric fields specs&lt;br /&gt;
  mat SDescription$ - the return value for the Descriptions of the String Specs&lt;br /&gt;
  mat NDescription$ - the return value for the Descriptions of the Numeric Specs&lt;br /&gt;
  mat SPos - the return value for the starting positions of the String Specs&lt;br /&gt;
  mat NPos - the return value for the starting positions of the Numeric Specs  &lt;br /&gt;
&lt;br /&gt;
=== fnReadSubs ===&lt;br /&gt;
This function reads the subscripts from a layout into Subs arrays.&lt;br /&gt;
&lt;br /&gt;
  fnReadSubs(Filename$,mat SSubs$,mat NSubs$,&amp;amp;Prefix$)&lt;br /&gt;
&lt;br /&gt;
=== fnReadKeyFiles ===&lt;br /&gt;
This function reads the list of key files from the layout.&lt;br /&gt;
&lt;br /&gt;
  fnReadKeyFiles(Layout$,mat Keys$)&lt;br /&gt;
&lt;br /&gt;
=== fnReadDescription$ ===&lt;br /&gt;
In the example program I used above, I am reading the Color File to get details about each color. The color file contains a colorcat code field, but I want to display the colorcat description. The colorcat file contains a few details about a color category, and it is indexed based on colorcat code:&lt;br /&gt;
&lt;br /&gt;
  route.dat, RT_&lt;br /&gt;
  route.key, CODE&lt;br /&gt;
  recl=512&lt;br /&gt;
  ===================================================&lt;br /&gt;
  CODE,           Routing Code,                C    6&lt;br /&gt;
  NAME,           Routing Name Description,    C   30&lt;br /&gt;
  MOFT,           T/A/C (truck/air/courier),   C    1&lt;br /&gt;
  SHIPPINGDAY,    Day of Week for Shipping,    C    7&lt;br /&gt;
&lt;br /&gt;
Now, as you know, in the above example, we have already opened the ColorCat File, and we have opened and read a Color record.&lt;br /&gt;
 &lt;br /&gt;
  04020    let colorfile=fnopen(&amp;quot;color&amp;quot;,mat color$,mat color,mat form$)&lt;br /&gt;
  04030    let colorcatfile=fnopen(&amp;quot;colorcat&amp;quot;,mat colorcat$,mat colorcat,mat form$,1)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  30120       read #colorfile, using form$(colorfile) : mat color$, mat color eof Ignore&lt;br /&gt;
  30180       LET ccode$=color$(CO_CODE) !:&lt;br /&gt;
              LET Name$=color$(CO_NAME)&lt;br /&gt;
&lt;br /&gt;
Now all that’s left to do is to take the Color File’s ColorCat code and use it to look up the ColorCat File’s description.&lt;br /&gt;
&lt;br /&gt;
  30190 LET ColorCat$ = fnReadDescription$(ColorCatFile, CC_NAME, Color$(CO_CATEGORY),&lt;br /&gt;
    mat ColorCat$, mat ColorCat, mat form$)&lt;br /&gt;
&lt;br /&gt;
Lets take a look at how this function works:&lt;br /&gt;
  FNREADDESCRIPTION$(Fl,Subscript,key$,mat F$,mat F,mat fm$)&lt;br /&gt;
&lt;br /&gt;
  FL – File Handle for file to use (Route File).&lt;br /&gt;
  SUBSCRIPT – Index of field in record to use (should be taken from file layout)&lt;br /&gt;
    (RT_NAME, which should equal 2 after opening routefile (unless we change the&lt;br /&gt;
    file layout later)).&lt;br /&gt;
  KEY$ - Item that should match a key in this file somewhere (in this case it is&lt;br /&gt;
    the route code from the farm record).&lt;br /&gt;
  MAT F$ &amp;amp; MAT F - Work Variables to hold a file record from the file we are reading&lt;br /&gt;
    – they have to be dimensioned properly, which is why we use our colorcat$ and our&lt;br /&gt;
    colorcat for these parameters.&lt;br /&gt;
  MAT FM$ - This will need to be our array of form statements, so the function can&lt;br /&gt;
    read the file properly.&lt;br /&gt;
&lt;br /&gt;
=== fnReadUnopenedDescription$ ===&lt;br /&gt;
This function accomplishes the same thing as fnReadDescription except that it opens the data file for you. It is slower then FnReadDescription$, but it is easier to use.&lt;br /&gt;
&lt;br /&gt;
  FnReadUnopenedDescription$(Layout$,key$*255;Field)&lt;br /&gt;
  &lt;br /&gt;
  Layout$ - the layout of the file we are reading&lt;br /&gt;
  key$ - the key of the record to be read&lt;br /&gt;
  Field - the element of the data file to return. If not given, this defaults to 2,&lt;br /&gt;
    so sometimes it is a good idea to design your data files so that string field&lt;br /&gt;
    number two is a descriptive field, like Name or Description.&lt;br /&gt;
&lt;br /&gt;
=== fnReadNumber ===&lt;br /&gt;
FnReadNumber does the same thing that ReadDescription does except it reads a numeric field instead of a description.&lt;br /&gt;
&lt;br /&gt;
Lets take a look at how this function works:&lt;br /&gt;
  FNREADNUMBER(Fl,subscript,key$,mat F$,mat F,mat fm$)&lt;br /&gt;
&lt;br /&gt;
  FL – File Handle for file to use (Route File).&lt;br /&gt;
  SUBSCRIPT – Index of field in record to use (should be taken from file layout)&lt;br /&gt;
    (RT_NAME, which should equal 2 after opening routefile (unless we change the&lt;br /&gt;
    file layout later)).&lt;br /&gt;
  KEY$ - Item that should match a key in this file somewhere (in this case it is&lt;br /&gt;
    the route code from the farm record).&lt;br /&gt;
  MAT F$ &amp;amp; MAT F - Work Variables to hold a file record from the file we are reading&lt;br /&gt;
    – they have to be dimensioned properly, which is why we use our colorcat$ and our&lt;br /&gt;
    colorcat for these parameters.&lt;br /&gt;
  MAT FM$ - This will need to be our array of form statements, so the function can&lt;br /&gt;
    read the file properly.&lt;br /&gt;
&lt;br /&gt;
=== fnReadUnopenedNumber ===&lt;br /&gt;
This function accomplishes the same thing as fnReadNumber except that it opens the data file for you. It is slower then FnReadNumber, but it is easier to use.&lt;br /&gt;
&lt;br /&gt;
  FnReadUnopenedNumber(Layout$,key$*255;Field)&lt;br /&gt;
  &lt;br /&gt;
  Layout$ - the layout of the file we are reading&lt;br /&gt;
  key$ - the key of the record to be read&lt;br /&gt;
  Field - the element of the data file to return. If not given, this defaults to 2,&lt;br /&gt;
    so sometimes it is a good idea to design your data files so that string field&lt;br /&gt;
    number two is a descriptive field, like Name or Description.&lt;br /&gt;
&lt;br /&gt;
=== fnReadRelativeDescription$ ===&lt;br /&gt;
This function is the same as fnReadDescription$ but for Relative Files.&lt;br /&gt;
&lt;br /&gt;
  FnReadRelativeDescription$(FileNumber,SubscriptToRead,RecordNumber,mat F$,mat F,mat form$)&lt;br /&gt;
&lt;br /&gt;
=== fnReadRelUnopenedDescription$ ===&lt;br /&gt;
This is the same as ReadUnopenedDescription$ but for Relative Files.&lt;br /&gt;
&lt;br /&gt;
  fnReadRelUnopenedDescription(LayoutName$,RecordNumber;Field)&lt;br /&gt;
&lt;br /&gt;
=== fnReadRelativeNumber ===&lt;br /&gt;
This is the same as fnReadNumber but for Relative Files.&lt;br /&gt;
&lt;br /&gt;
  fnReadRelativeNumber(FileNumber,SubscriptToRead,RecordNumber,mat F$,mat f,mat Form$)&lt;br /&gt;
&lt;br /&gt;
=== fnReadRelUnopenedNumber ===&lt;br /&gt;
This is the same as fnReadUnopenedNumber but for Relative Files.&lt;br /&gt;
&lt;br /&gt;
  fnReadRelUnopenedNumber(LayoutName$,RecordNumber;Field)&lt;br /&gt;
&lt;br /&gt;
=== fnGetFileNumber ===&lt;br /&gt;
FnGetFileNumber is a simple function to find a valid unused file handle. If you use this function in all of your programs, they will become much more portable, as you will never have to worry about your file handles fighting with each other. The function will return 0 if no free file number was found (but with 999 of them available now, I have never seen it happen).&lt;br /&gt;
&lt;br /&gt;
  FNGETFILENUMBER(;X,Count)&lt;br /&gt;
&lt;br /&gt;
  X – This optional parameter will specify where to start looking.&lt;br /&gt;
  Count - This optional parameter will specify how many file numbers to find in&lt;br /&gt;
    a row. If count is 3, then fnGetFileNumber will return the first filenumber in&lt;br /&gt;
    the first gap of three unused file numbers that it finds.&lt;br /&gt;
&lt;br /&gt;
=== fnUniqueKey ===&lt;br /&gt;
This function tests to see if a given key is unique to the specified file. This function is very useful for situations where you need to ensure that the user-entered key is unique.&lt;br /&gt;
&lt;br /&gt;
  FnUniqueKey(Fl,key$*255)&lt;br /&gt;
&lt;br /&gt;
  FL – The file number of the opened file.&lt;br /&gt;
  Key$ - This is the key to test. If this key is the key for a preexisting record in&lt;br /&gt;
    the file, the function will return false. If this key can not be found in the file,&lt;br /&gt;
    the function will return true.&lt;br /&gt;
&lt;br /&gt;
=== fnReadAllKeys ===&lt;br /&gt;
This function will read through a file, returning the specified element(s) from each record into (a) dynamically dimensioned array(s). For example, I could tell it to give me the Inventory Code for every inventory item in my database in one array, while placing the Inventory Description (name) for each item into the corresponding position in another array.&lt;br /&gt;
&lt;br /&gt;
  FnReadAllKeys(Fl,mat f$,mat f,mat fm$,sub1,mat out1$;sub2,mat out2$)&lt;br /&gt;
&lt;br /&gt;
  FL – The file handle for the already opened file in question.&lt;br /&gt;
  MAT F$ - Work array with a size that corresponds to the number of string elements&lt;br /&gt;
    in the record (this is calculated automatically in the Open statement, if you used&lt;br /&gt;
    this library to open the file).&lt;br /&gt;
  MAT F – Work array with a size that corresponds to the number of numeric elements in&lt;br /&gt;
    the record (this is calculated automatically in the Open statement, if you used this&lt;br /&gt;
    library to open the file).&lt;br /&gt;
  MAT fm$ - Array of Forms statement. FM$(FL) must be the form statement for this file&lt;br /&gt;
    (this is calculated automatically in the Open statement, if you used this library&lt;br /&gt;
    to open the file).&lt;br /&gt;
  Sub1 – Subscript of the element to return in the first array&lt;br /&gt;
  MAT out1$ - Array in which to return the data. This array will be resized to match&lt;br /&gt;
    the number of records in the file.&lt;br /&gt;
  Sub2 – Subscript of the element to return in the second array. This is optional.&lt;br /&gt;
    If it is specified, you must give MAT out2$, or BR will return an error.&lt;br /&gt;
  MAT out2$ - Array in which to return the second (optional) parameter. This array&lt;br /&gt;
    will be resized to match the number of records in the file. This parameter MUST&lt;br /&gt;
    be provided when Sub2 is given (non-zero). This parameter will not be used if Sub2&lt;br /&gt;
    is not given or is given as 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If I wanted to implement the above example, I would say:&lt;br /&gt;
&lt;br /&gt;
  FnReadAllKeys(InventFile,mat Invent$,mat Invent,mat Form$,IN_Code,mat InvtList$,IN_Name,mat InvtNames$)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== fnReadMatchingKeys ===&lt;br /&gt;
&lt;br /&gt;
This function will read through a file, returning the specified element(s) from each record where the key matches the specified key into (a) dynamically dimensioned array(s). This function is the same as the above function except this one will filter the results, returning only those records where the key matches the specified key.&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
  FnReadMatchingKeys(Fl,mat f$,mat f,mat fm$,key$,keysub,sub1,mat out1$;sub2,mat out2$)&lt;br /&gt;
&lt;br /&gt;
  FL – The file handle for the already opened file in question.&lt;br /&gt;
  MAT F$ - Work array with a size that corresponds to the number of string elements in&lt;br /&gt;
    the record (this is calculated automatically in the Open statement, if you used this&lt;br /&gt;
    library to open the file).&lt;br /&gt;
  MAT F – Work array with a size that corresponds to the number of numeric elements in the&lt;br /&gt;
    record (this is calculated automatically in the Open statement, if you used this library&lt;br /&gt;
    to open the file).&lt;br /&gt;
  MAT fm$ - Array of Forms statement. FM$(FL) must be the form statement for this file&lt;br /&gt;
    (this is calculated automatically in the Open statement, if you used this library to open&lt;br /&gt;
    the file).&lt;br /&gt;
  Key$ - Only records where the key field matches key$ will be returned.&lt;br /&gt;
  Keysub – This tells the function which element is the key element for this particular file number.&lt;br /&gt;
  Sub1 – Subscript of the element to return in the first array.&lt;br /&gt;
  MAT out1$ - Array in which to return the data. This array will be resized to match the number&lt;br /&gt;
    of records in the file.&lt;br /&gt;
  Sub2 – Subscript of the element to return in the second array. This is optional. If it is&lt;br /&gt;
    specified, you must give MAT out2$, or BR will return an error.&lt;br /&gt;
  MAT out2$ - Array in which to return the second (optional) parameter. This array will be&lt;br /&gt;
    resized to match the number of records in the file. This parameter MUST be provided when&lt;br /&gt;
    Sub2 is given (non-zero). This parameter will not be used if Sub2 is not given or is given as 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== fnReadAllNewKeys ===&lt;br /&gt;
&lt;br /&gt;
This function will read through a file, returning the specified element(s) from each record that isn’t already there into (a) dynamically dimensioned array(s). This function is the same as the above function, except this one will filter the results returning only those records that don’t already exist in the array (eliminating duplicates).&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
  FnReadAllNewKeys(Fl,mat f$,mat f,mat fm$,sub1,mat out1$; dont_reset,sub2,mat out2$)&lt;br /&gt;
&lt;br /&gt;
  FL – The file handle for the already opened file in question.&lt;br /&gt;
  MAT F$ - Work array with a size that corresponds to the number of string elements in the&lt;br /&gt;
    record (this is calculated automatically in the Open statement, if you used this library&lt;br /&gt;
    to open the file).&lt;br /&gt;
  MAT F – Work array with a size that corresponds to the number of numeric elements in the&lt;br /&gt;
    record (this is calculated automatically in the Open statement, if you used this library&lt;br /&gt;
    to open the file).&lt;br /&gt;
  MAT fm$ - Array of Forms statement. FM$(FL) must be the form statement for this file (this&lt;br /&gt;
    is calculated automatically in the Open statement, if you used this library to open the file).&lt;br /&gt;
  Sub1 – Subscript of the element to return in the first array.&lt;br /&gt;
  MAT out1$ - Array in which to return the data. This array will be resized to match the number of&lt;br /&gt;
    records in the file.&lt;br /&gt;
  Dont_reset – By default the array will clear the contents of the arrays that are passed in. This&lt;br /&gt;
    Boolean flag will instruct the function to not empty the passed in arrays.&lt;br /&gt;
  Sub2 – Subscript of the element to return in the second array. This is optional. If it is specified,&lt;br /&gt;
    you must give MAT out2$, or BR will return an error.&lt;br /&gt;
  MAT out2$ - Array in which to return the second (optional) parameter. This array will be resized to&lt;br /&gt;
    match the number of records in the file. This parameter MUST be provided when Sub2 is given&lt;br /&gt;
    (non-zero). This parameter will not be used if Sub2 is not given or is given as 0.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== FnReadFilterKeys ===&lt;br /&gt;
&lt;br /&gt;
This function by Mikhail Zheleznov is a modification of the above functions. Like its predecessors, it reads an entire file, populating the specified arrays with data from all or some of the records in the file. The given subscripts specify which fields to return from each record. The key given specifies search criteria for the records. The filter specifies filtering criteria that can be preformed on the data before it is returned. &lt;br /&gt;
&lt;br /&gt;
  FnReadFilterKeys(Fl,Mat F$,Mat F,Mat Fm$,Key$,Keyfld,Sub1,Mat Out1$;Filter$,Filter_Sub,&lt;br /&gt;
    Readlarger,Sub2,Mat Out2$, Sub3, Mat Out3$, Sub4,Mat Out4$)&lt;br /&gt;
&lt;br /&gt;
  FL – The file handle for the already opened file in question.&lt;br /&gt;
  MAT F$ - Work array with a size that corresponds to the number of string elements in the&lt;br /&gt;
    record (this is calculated automatically in the Open statement, if you used this library&lt;br /&gt;
    to open the file).&lt;br /&gt;
  MAT F – Work array with a size that corresponds to the number of numeric elements in the&lt;br /&gt;
    record (this is calculated automatically in the Open statement, if you used this library&lt;br /&gt;
    to open the file).&lt;br /&gt;
  MAT fm$ - Array of Forms statement. FM$(FL) must be the form statement for this file (this&lt;br /&gt;
    is calculated automatically in the Open statement, if you used this library to open the file).&lt;br /&gt;
  Key$ - The key to search for in the read statements&lt;br /&gt;
  Keyfld – the subscript of the key field in the data file. This must match the key field&lt;br /&gt;
    specified in the data file otherwise the function won’t work.&lt;br /&gt;
  Sub1 – Subscript of the element to return in the first array.&lt;br /&gt;
  MAT out1$ - Array in which to return the data. This array will be resized to match the&lt;br /&gt;
    number of records in the file.&lt;br /&gt;
  Filter$ – This optional parameter identifies matches to search for in the records. It&lt;br /&gt;
    works in conjunction with Filter_Sub&lt;br /&gt;
  Filter_Sub – This parameter specifies which field to look for in the records for matches&lt;br /&gt;
    to Filter$. Only records which have Filter$ in the specified field will be returned.&lt;br /&gt;
  Sub2 – Subscript of the element to return in the second array. This is optional. If it&lt;br /&gt;
    is specified, you must give MAT out2$, or BR will return an error.&lt;br /&gt;
  MAT out2$ - Array in which to return the second (optional) field. This array will be&lt;br /&gt;
    resized to match the number of records in the file. This parameter MUST be provided&lt;br /&gt;
    when Sub2 is given (non-zero). This parameter will not be used if Sub2 is not given&lt;br /&gt;
    or is given as 0.&lt;br /&gt;
  Sub3 – Subscript of the element to return in the third array. This is optional. If it&lt;br /&gt;
    is specified, you must give MAT out3$, or BR will return an error.&lt;br /&gt;
  MAT out3$ - Array in which to return the third (optional) field. This array will be&lt;br /&gt;
    resized to match the number of records in the file. This parameter MUST be provided&lt;br /&gt;
    when Sub3 is given (non-zero). This parameter will not be used if Sub3 is not given&lt;br /&gt;
    or is given as 0.&lt;br /&gt;
  Sub4 – Subscript of the element to return in the fourth array. This is optional. If it&lt;br /&gt;
    is specified, you must give MAT out4$, or BR will return an error.&lt;br /&gt;
  MAT out4$ - Array in which to return the fourth (optional) field. This array will be&lt;br /&gt;
    resized to match the number of records in the file. This parameter MUST be provided&lt;br /&gt;
    when Sub4 is given (non-zero). This parameter will not be used if Sub4 is not given&lt;br /&gt;
    or is given as 0.&lt;br /&gt;
&lt;br /&gt;
This function was written by Mikhail Zheleznov for the fileIO library.&lt;br /&gt;
&lt;br /&gt;
=== fnMakeUniqueKey$ ===&lt;br /&gt;
This function generates a unique key for a given file. This is useful if you do not care what the key is, but it needs to be unique. I use this function in situations where the user never needs to know what the given key is. &lt;br /&gt;
&lt;br /&gt;
This function reads the key length for the given file. Then it returns a string that is the right length, which is generated by counting in binary until a key is found that does not appear in the file. The first key found for a 4 byte key field would be chr$(0)&amp;amp;chr$(0)&amp;amp;chr$(0)&amp;amp;chr$(0). If that key was already in use in the file, the function would return chr$(0)&amp;amp;chr$(0)&amp;amp;chr$(0)&amp;amp;chr$(1). If that one was also in use, it would then try chr$(0)&amp;amp;chr$(0)&amp;amp;chr$(0)&amp;amp;chr$(2), and so on until it found one that wasn’t in use.&lt;br /&gt;
&lt;br /&gt;
  FnMakeUniqueKey$(fl)&lt;br /&gt;
&lt;br /&gt;
  FL – This is the file number of the opened file for the desired key.&lt;br /&gt;
&lt;br /&gt;
=== fnLog &amp;amp; fnErrLog ===&lt;br /&gt;
These next two functions are functions to aid in logging. When you call either of these two functions, you give them a string that you wish to log. They will open a textfile called FileIO.log and add a line to the end of it containing some user information such as login_name and session$, and the string that you specified. FnErrLog does the same thing as fnLog except it also logs the Error Number and the Line.&lt;br /&gt;
&lt;br /&gt;
The syntax is:&lt;br /&gt;
&lt;br /&gt;
  FnLog(string$)&lt;br /&gt;
  FnErrLog(String$)&lt;br /&gt;
&lt;br /&gt;
=== fnNotInFile ===&lt;br /&gt;
This function will determine if a non-key element in a line is unique. It works almost exactly like fnUniqueKey specified above, except that it allows you to enter the subscript value of the element you are checking for uniqueness. You can use this to look for uniqueness in any field, not just in the key field. Additionally, the search engine used by this function looks for a partial match, and will only return true if the given string is not found anywhere in the specified element for the given file.&lt;br /&gt;
&lt;br /&gt;
  FnNotInFile(string$*100,filename$,sub)&lt;br /&gt;
&lt;br /&gt;
  String$ - Value to check for uniqueness in this file.&lt;br /&gt;
  Filename$ - This is the name of the file layout of the file you want to check. This file&lt;br /&gt;
    does not have to be open in order for you to search it, because the function will open&lt;br /&gt;
    it for you.&lt;br /&gt;
  Sub – This is the subscript value of the element you are checking.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== fnReadLayouts ===&lt;br /&gt;
This function reads the file layout folder and returns all the applicable layouts in the passed in array.&lt;br /&gt;
&lt;br /&gt;
  FnReadLayouts(mat Dirlist$)&lt;br /&gt;
&lt;br /&gt;
  Mat Dirlist$ - After running the function, mat Dirlist$ will contain a list of all the&lt;br /&gt;
    file layouts that FileIO can find.&lt;br /&gt;
&lt;br /&gt;
=== fnDoesLayoutExist ===&lt;br /&gt;
This function returns true if the given file layout exists. It returns false if the layout does not exist.&lt;br /&gt;
 &lt;br /&gt;
  FnDoesLayoutExist(layout$)&lt;br /&gt;
&lt;br /&gt;
  Layout$ - Layout to look for&lt;br /&gt;
&lt;br /&gt;
=== fnKey$ ===&lt;br /&gt;
This function formats the key for the given file number.&lt;br /&gt;
&lt;br /&gt;
  FnKey$(FileNumber, Key$)&lt;br /&gt;
  &lt;br /&gt;
  FileNumber - the file number we are formatting the key for&lt;br /&gt;
  Key$ - the key we are trying to format.&lt;br /&gt;
&lt;br /&gt;
=== fnBuildKey$ ===&lt;br /&gt;
This function will return they key for a given record in a data file. It actually reads the file layout and builds the key to match the layout.&lt;br /&gt;
&lt;br /&gt;
  FnBuildKey$(Layout$, Mat F$, Mat F; Keynum)&lt;br /&gt;
  &lt;br /&gt;
  Layout$ - the name of the data file to build the key for.&lt;br /&gt;
  Mat F$ - the string array of the file object&lt;br /&gt;
  Mat F - the numeric array of the file object&lt;br /&gt;
  KeyNum - This optional parameter specifies which of the key files in&lt;br /&gt;
    the given layout the key should be built for.&lt;br /&gt;
&lt;br /&gt;
=== fnReadRecordWhere$ ===&lt;br /&gt;
This function returns the record where the given element matches the given value. It does not depend on any key files, and it can be used to locate a record based on any element. However, it loops through the entire data file to do this and it could be a bit slow for large data files. This function opens the file for you, so the file does not have to be already opened.&lt;br /&gt;
&lt;br /&gt;
  FnReadRecordWhere$(Layout$,SearchSub,SearchKey$*255,ReturnSub)&lt;br /&gt;
  &lt;br /&gt;
  Layout$ - the layout of the file we are searching&lt;br /&gt;
  SearchSub - Subscript of the element to look in&lt;br /&gt;
  SearchKey$ - The value we are looking for&lt;br /&gt;
  ReturnSub - Subscript of the element to return&lt;br /&gt;
&lt;br /&gt;
=== fnUpdateFile ===&lt;br /&gt;
This function checks and Updates a data file if it needs to be updated, by opening and then closing the data file.&lt;br /&gt;
&lt;br /&gt;
  fnUpdateFile(FileLayout$)&lt;br /&gt;
  &lt;br /&gt;
  FileLayout$ - The name of the file to update&lt;br /&gt;
&lt;br /&gt;
=== fnDisplayLength ===&lt;br /&gt;
This function calculates the display length of a field based on its form spec.&lt;br /&gt;
&lt;br /&gt;
  fnDisplayLength(Spec$)&lt;br /&gt;
  &lt;br /&gt;
  Spec - the Form Spec to return the display length of.&lt;br /&gt;
&lt;br /&gt;
=== fnLength ===&lt;br /&gt;
This function calculates the length on disk of a field based on its form spec.&lt;br /&gt;
&lt;br /&gt;
  fnLength(Spec$)&lt;br /&gt;
  &lt;br /&gt;
  Spec - the Form Spec to return the display length of.&lt;br /&gt;
&lt;br /&gt;
=== fnDataCrawler ===&lt;br /&gt;
This function launches the Data Crawler as a function, so you can make your own programs link to it. Special thanks to Mikhail Zheleznov for turning the DataCrawler into a library function.&lt;br /&gt;
&lt;br /&gt;
  fnDataCrawler(Layout$;SRow$,SCol$,Rows$,Cols$)&lt;br /&gt;
&lt;br /&gt;
=== fnDataEdit ===&lt;br /&gt;
This function launches the DataGrid as a function, so you can make your own programs link to it. Special thanks to Mikhail Zheleznov for turning the DataGrid into a library function.&lt;br /&gt;
&lt;br /&gt;
   fnDataEdit(Layout$;SRow$,SCol$,Rows$,Cols$)&lt;br /&gt;
&lt;br /&gt;
== FileIO Add-on Packages ==&lt;br /&gt;
&lt;br /&gt;
Many FileIO Add-on packages are currently in the works.&lt;br /&gt;
&lt;br /&gt;
=== ScreenIO Library ===&lt;br /&gt;
&lt;br /&gt;
The [[ScreenIO Library]] is a sister library to the FileIO library. The ScreenIO library requires the FileIO library in order to run.&lt;br /&gt;
&lt;br /&gt;
The ScreenIO library is a complete Rapid Application Design tool that enables you to implement custom screen functions anywhere in your exiting programs.&lt;br /&gt;
&lt;br /&gt;
If you call the ScreenIO Library as a function library, you call a function called fnFM and tell it which screen you wish to use. The ScreenIO library loads your user interface, loads your data files, and preforms all the file maintenance operations you have designed into your screens.&lt;br /&gt;
&lt;br /&gt;
You can find out the latest information about the ScreenIO library in the ScreenIO page.&lt;br /&gt;
&lt;br /&gt;
== What’s New ==&lt;br /&gt;
=== Spring 2009 ===&lt;br /&gt;
==== New Functions ====&lt;br /&gt;
The FileIO Library has been updated in Spring 2009 to provide several new functions:&lt;br /&gt;
&lt;br /&gt;
  fnReadRecordWhere&lt;br /&gt;
  fnKey$&lt;br /&gt;
  fnBuildKey$&lt;br /&gt;
  fnReadUnopenedDescription$&lt;br /&gt;
  fnUpdateFile&lt;br /&gt;
  fnDisplayLength&lt;br /&gt;
  fnLength&lt;br /&gt;
  fnReadLayoutHeader&lt;br /&gt;
  fnReadEntireLayout&lt;br /&gt;
&lt;br /&gt;
==== Speed Increases ====&lt;br /&gt;
Thanks to the BR Profiler, we have increased the speed of FileIO fnOpen function by ten times when running over a LAN and by 100 times when running over the internet using Client Server.&lt;br /&gt;
&lt;br /&gt;
In order to get the new Speed Upgrades, you will need to make sure that you use the latest copy of the [[#fnOpen_Function|fnOpen]] function in each one of your programs that use FileIO.&lt;br /&gt;
&lt;br /&gt;
==== Network FileIO ====&lt;br /&gt;
This version of FileIO has been optimized to work better in network situations.&lt;br /&gt;
&lt;br /&gt;
==== FnSettings ====&lt;br /&gt;
There are more configuration options in the [[#fnSettings_.28Global_Settings_Code.29|fnSettings]] routine.&lt;br /&gt;
&lt;br /&gt;
==== Automatic Update Speed Fix ====&lt;br /&gt;
The automatic update proceedure has been made to run more then 100 times faster then before according to our benchmarking tests.&lt;br /&gt;
&lt;br /&gt;
=== Fall 2008 ===&lt;br /&gt;
==== DataCrawler Grid ====&lt;br /&gt;
&lt;br /&gt;
By popular request we added a read/write version to the data crawler. This version works exactly the same as the datacrawler did before but it displays all the contents of your data files in a grid instead of a listview. &lt;br /&gt;
&lt;br /&gt;
When you run the fileIO library as a program, it launches a tool known as the [[#DataCrawler|DataCrawler]]. The DataCrawler shows a listview displaying all your layout files in it. If you select one, it builds another listview with all the data in your selected data file.&lt;br /&gt;
&lt;br /&gt;
If you are looking at the first list of all your file layouts, and you press F5, a grid will be build displaying all the data in your data files. You can change any of the records you like, and when you&#039;re done, your changes will be saved to the data file. Additionally, you can Add or Delete records using the buttons at the bottom. Any changes you make are not written to the disk until you click the &amp;quot;Save&amp;quot; button. If you press ESC (Cancel) the grid is closed and all changes you made sinse the last save are lost.&lt;br /&gt;
&lt;br /&gt;
This tool is for programmers only. Do not give your end users access to the DataCrawler.&lt;br /&gt;
&lt;br /&gt;
Use the DataCrawler at your own risk. Gabriel Bakker and Sage AX are not responsible for any harm that comes to your data files through the use of this or any other tools we offer.&lt;br /&gt;
&lt;br /&gt;
The DataCrawler is not designed to be used to maintain your data files. It can be used carefully to correct small things in your data files.&lt;br /&gt;
&lt;br /&gt;
==== Support for Nonstandard Paths ====&lt;br /&gt;
&lt;br /&gt;
Many BR Vendors keep different versions of the same data files in different locations. For example, sometimes a BR vendor will use a different Data folder to represent data for different Warehouses, or Customers. In cases like this it is necessary for your programs to specify the path to your data files. They may do so by specifying the optional &amp;quot;PATH&amp;quot; parameter to your data files. See the section [[#fnOpenFile]] for more information.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Support for Nonstandard Layout Files Path ====&lt;br /&gt;
&lt;br /&gt;
Old versions of the fileIO library required you to place all your file layouts in a subfolder of your program directory called &amp;quot;filelay&amp;quot;. We have now changed the Fileio library to allow you to place your file layouts any place you want. The only requirement is that they are all together in one folder by themselves.&lt;br /&gt;
&lt;br /&gt;
If you use a nonstandard path in the fileIO library, it is necessary to make a change to the [[#fnSettings_.28Global_Settings_Code.29|fnSettings]] code in your copy of fileio.br.&lt;br /&gt;
&lt;br /&gt;
==== Prompt on Create ====&lt;br /&gt;
&lt;br /&gt;
The FileIO library automatically creates any data files that it can&#039;t find. This was done to make it easier to deploy your finished programs - if you had any empty data files you could omit them from the packages and they would be created when they were needed, on the fly.&lt;br /&gt;
&lt;br /&gt;
The current version of the FileIO library contains the same ability. However, it prompts you before creating any data files. This helps to avoid bugs that happen from incorrectly specifying the path to your data files.&lt;br /&gt;
&lt;br /&gt;
However, if you do intend for your data files to be autocreated, then you probably don&#039;t want your end users to modify them. Therefore, you can use the PromptOnCreate setting in the [[#fnSettings_.28Global_Settings_Code.29|fnSettings]] code to specify. If this value is set to true, then the fileIO library will prompt you whenever it attempts to Autocreate a data file. If it is set to false, then the fileIO library will create the data files without prompting you, like it always did before.&lt;br /&gt;
&lt;br /&gt;
==== fnSettings ====&lt;br /&gt;
&lt;br /&gt;
The newest version of the FileIO library supports some features that require you to specify Global Settings values. These are done by modifying the contents of the [[#fnSettings_.28Global_Settings_Code.29|fnSettings]] routine at the beginning of the fileIO library.&lt;br /&gt;
&lt;br /&gt;
=== Fall 2006 ===&lt;br /&gt;
Many improvements have been made in the FileIO library over the summer. This section is intended to acquaint you with the highlights of those changes. Most of these improvements were built from ideas generated during the discussion at the April conference.&lt;br /&gt;
&lt;br /&gt;
==== Intermixed String and Numeric Specs ====&lt;br /&gt;
The File Library has been expanded to allow the reading of data files that contain mixed string and numeric specs. This is to aid those of you who are planning on implementing the FileIO Library on existing data files which may not be organized with strings first and numbers second.&lt;br /&gt;
&lt;br /&gt;
The central idea of the FileIO Library is based upon the reading of your data files into a String and Numeric array. This will enable you to refer to the fields in your file by using a named subscript, saying F$(FM_NAME) to refer, for example, to the farm file’s name field. The advantage to this is that when you change the file layout, all your existing programs will not have to be modified, because they will only be looking at F$(FM_NAME). If the name field changes from the third string field to the fourth, the value of FM_NAME will also change, and you won’t have to worry about updating your data files.&lt;br /&gt;
&lt;br /&gt;
However, in order to support the reading of a data file with intermixed string and numeric specs, the generated form statement will actually calculate the position of any fields that are not in order, so that the file read statement will still return all string fields first (into your string array) and the numeric fields second (into your numeric array). You do not need to worry about this; the library does it for you. All you have to do is read your file and use the data values.&lt;br /&gt;
&lt;br /&gt;
The only thing that is required is making sure that all your string subscript names end with a “$”. This will tell the library that they are strings. Thank you, George, for this suggestion.&lt;br /&gt;
&lt;br /&gt;
==== Versioning / Automatic Updates ====&lt;br /&gt;
The file layouts have been expanded to contain a version number. This version number will be used to determine when a file needs to be updated. The version number is the third parameter in the file layout.&lt;br /&gt;
&lt;br /&gt;
Any time you wish to change your file layouts, simply increment this version number. Each time the library attempts to open a data file, the file’s version is checked and compared with the version in the file layout. If the file layout has been changed (if the version in the file layout is greater then the version in the file) then the file will be updated to the latest version. Depending on the file size this may take a couple of moments. A simple progress bar will be displayed on screen while this is happening. The progress bar will be displayed in its own window, so it should not affect anything your programs may have had on screen.&lt;br /&gt;
&lt;br /&gt;
The library uses the following procedure for updating a file. First, the file is copied to a backup file (prefixed by the letter ‘o’ for old). So color.dat would become ocolor.dat, and color.key would become ocolor.key. Then the new file is created and marked with the proper version number. (color.dat, color.key). The old file is opened in read-only mode, and the new file is opened for OutIn. The update routine actually reads through the old file layout, and one record at a time creates a new record, using the new file layout, with the same data, saving it to the new data file.&lt;br /&gt;
&lt;br /&gt;
When it is done upgrading, the progress bar window is closed, and the file is reopened in the fashion you described in your call to fnOpen, and flow returns to your program as though nothing unusual has happened.&lt;br /&gt;
&lt;br /&gt;
If an error occurs during processing, the routine will do what it can to roll your data files back to the previous version, but please make frequent backups of your data files anyway, just to be safe.&lt;br /&gt;
&lt;br /&gt;
==== Error Checking – If there is a mistake in the file layout ====&lt;br /&gt;
The routine attempts to discover the cause of the error in the case that one is encountered due to a missing file, a file sharing violation, or an invalid or corrupt file layout. If this should happen, the program is paused, and a text message is printed out explaining the most likely source for the error, including what part of the file layout, if any, may have caused the error.&lt;br /&gt;
&lt;br /&gt;
You may then examine the printed text, and the contents of the BR system variables ERR and LINE to determine the problem. If you type “GO”, the next line will be execute “system”, ending your program.&lt;br /&gt;
&lt;br /&gt;
If the file was in the middle of an upgrade when the error happened, it will be automatically rolled back to the previous version, so that when you fix the problem and try to run your program again, the file will again attempt to update from the beginning, and you won’t have to worry about corrupted data.&lt;br /&gt;
&lt;br /&gt;
However, please backup your data before upgrading your data files anyway, just to be safe.&lt;br /&gt;
&lt;br /&gt;
==== Implementation of Keys / Creation of New Data Files ====&lt;br /&gt;
The library has been expanded to automatically create all new data files, and to automatically update any existing files. This means that in the file layout header, two new fields that were previously ignored are no longer ignored. The RECL value that you specify in your file layout will be used, along with the description/definition of your keys file. When you open a new file (or update an existing one), the library will calculate the proper kps and kln by evaluating the key description. This key description must match up with subscript values from the data elements in your file, and more then one may be specified, but they must be separated with slashes (/). If I wanted my Farm File to be keyed based on CODE and NAME, the proper key description would be:&lt;br /&gt;
&lt;br /&gt;
  farm.key, CODE/NAME&lt;br /&gt;
&lt;br /&gt;
The library will then look up the position and length on disk of the CODE and NAME fields and put them together to create the proper keys during an update or creation of a new file. &lt;br /&gt;
&lt;br /&gt;
==== DataCrawler ====&lt;br /&gt;
Perhaps the most exciting new addition to the library is the addition of a programming tool I like to call a DataCrawler. If you run the FileIO Library directly as a program, instead of using it as a library, it will function as a DataCrawler. The DataCrawler requires a New Gui version of BR, as it requires a ListView to be able to properly and easily display the data in your files.&lt;br /&gt;
&lt;br /&gt;
If you run it in an older version of BR you will get a message, telling you to run it in a newer copy. If you run it in a New Gui version of BR with CONFIG GUI OFF, then GUI will be turned temporarily on for the use of the DataCrawler and then turned off again when you are finished. If you run it in a New Gui version of BR with GUI ON, it will just run normally.&lt;br /&gt;
&lt;br /&gt;
When you run the DataCrawler, first you will see a ListView displaying every file layout it can find in the filelay folder. If you select a file, the DataCrawler will open a large ListView with as many columns as there are fields in the file. The Column Headings will come from the element descriptions in your data files, and the column widths will come from the displayed width of the fields. There will be a row for every record in your data file, and you can resize the column widths, and scroll around the data file to view the raw data of your BR data files on disk.&lt;br /&gt;
&lt;br /&gt;
If you are dealing with a particularly enormous data file (50,000+ records) it can take a moment to populate the ListView with the data in your data file. You may hit ESC to stop loading if you like, and view only the already loaded records.&lt;br /&gt;
&lt;br /&gt;
If you would like to look up a particular record (based only upon the primary key for the data file), you may press F4. This will give you a window which asks you to input the key or partial key. When you press enter, the file will be reloaded, starting at the key you specified and continuing on to the end of the file, or until you press ESC. The records you are looking for should appear at the top of the ListView.&lt;br /&gt;
&lt;br /&gt;
To reset the ListView and look at the contents of the entire file again, simply press F4, and enter a blank (“”) key.&lt;br /&gt;
&lt;br /&gt;
Finally, as with any ListView, you may resort your data by clicking on any of the column headings. Then you can use the slider bar at the right to scroll down to the record you desire.&lt;br /&gt;
&lt;br /&gt;
This is a programming tool and is not designed to be used by an end user. This tool will open your file in read-only mode. It will not allow you to modify the data; I leave that as an exercise for the reader. However, it will update any datafiles you view to the latest version (if they need to be updated) when it opens them, just as any other program that uses the library will do.&lt;br /&gt;
&lt;br /&gt;
== Appendix (Examples)==&lt;br /&gt;
&lt;br /&gt;
=== Example.br ===&lt;br /&gt;
  00010    ! example.br - This program is an example of for the data reading simplification&lt;br /&gt;
  00020    ! Copyright April 2006 by Gabriel Bakker&lt;br /&gt;
  00030    ! Distributed open source as a Christmas gift to brag members&lt;br /&gt;
  00040    !&lt;br /&gt;
  00100    execute &amp;quot;config gui off&amp;quot;&lt;br /&gt;
  01020    DIM form$(1)*255&lt;br /&gt;
  01030    DIM color$(1)*255,color(1)&lt;br /&gt;
  01040    DIM colorcat$(1)*255,colorcat(1)&lt;br /&gt;
  02020    library &amp;quot;fileio&amp;quot;: fnopenfile, fnreaddescription$&lt;br /&gt;
  04000 !&lt;br /&gt;
  04010 Openfiles: ! Open your files here&lt;br /&gt;
  04020    let colorfile=fnopen(&amp;quot;color&amp;quot;,mat color$,mat color,mat form$)&lt;br /&gt;
  04030    let colorcatfile=fnopen(&amp;quot;colorcat&amp;quot;,mat colorcat$,mat colorcat,mat form$,1)&lt;br /&gt;
  06000    ! gosub WriteFiles ! If you want to test this line, make sure to drop flag from 4030&lt;br /&gt;
  07000 !&lt;br /&gt;
  07010 MainBit: ! This&#039;un here&#039;s tha Main Bit&lt;br /&gt;
  07030    RESTORE #ColorFile:&lt;br /&gt;
  07100    ReadNextcolor: ! Read next record&lt;br /&gt;
  07120       read #ColorFile, using form$(ColorFile) : mat Color$, mat Color eof EndReadColor&lt;br /&gt;
  07180       PRINT Color$(co_name)&amp;amp;&amp;quot; (&amp;quot;&amp;amp;Color$(co_html)&amp;amp;&amp;quot;) is a member of the &#039;&amp;quot;;&lt;br /&gt;
  07190       PRINT trim$(fnReadDescription$(ColorcatFile,cc_Name,Color$(co_category),mat Colorcat$,mat Colorcat,mat form$))&amp;amp;&amp;quot;&#039; category.&amp;quot;&lt;br /&gt;
  07290       goto ReadNextColor&lt;br /&gt;
  07300    EndReadcolor: ! Finished with Color File&lt;br /&gt;
  08000    STOP&lt;br /&gt;
  25000 !&lt;br /&gt;
  25010 WriteFiles: ! Uncalled routine to demonstrate writing files&lt;br /&gt;
  25105       let color$(co_code)=&amp;quot;GD&amp;quot; !:&lt;br /&gt;
              let color$(co_Name)=&amp;quot;Gold&amp;quot; !:&lt;br /&gt;
              let color$(co_Category)=&amp;quot;YL&amp;quot; !:&lt;br /&gt;
              let color$(co_html)=&amp;quot;FFD700&amp;quot;&lt;br /&gt;
  25110       write #colorfile, using form$(colorfile): mat color$, mat color&lt;br /&gt;
  25115       let color$(co_code)=&amp;quot;LV&amp;quot; !:&lt;br /&gt;
              let color$(co_Name)=&amp;quot;Lavender&amp;quot; !:&lt;br /&gt;
              let color$(co_Category)=&amp;quot;BL&amp;quot; !:&lt;br /&gt;
              let color$(co_html)=&amp;quot;E6E6FA&amp;quot;&lt;br /&gt;
  25120       write #colorfile, using form$(colorfile): mat color$, mat color&lt;br /&gt;
  25125       let color$(co_Code)=&amp;quot;OR&amp;quot; !:&lt;br /&gt;
              let color$(co_Name)=&amp;quot;Orange&amp;quot; !:&lt;br /&gt;
              let color$(co_Category)=&amp;quot;YL&amp;quot; !:&lt;br /&gt;
              let color$(co_html)=&amp;quot;FFA500&amp;quot;&lt;br /&gt;
  25130       write #colorfile, using form$(colorfile): mat color$, mat color&lt;br /&gt;
  25205       let colorcat$(cc_Code)=&amp;quot;YL&amp;quot; !:&lt;br /&gt;
              let colorcat$(cc_Name)=&amp;quot;Yellows&amp;quot; !:&lt;br /&gt;
              let colorcat$(cc_html)=&amp;quot;FFFF00&amp;quot;&lt;br /&gt;
  25210       write #colorcatfile, using form$(colorcatfile): mat colorcat$,mat colorcat&lt;br /&gt;
  25215       let colorcat$(cc_Code)=&amp;quot;BL&amp;quot; !:&lt;br /&gt;
              let colorcat$(cc_Name)=&amp;quot;Blues&amp;quot; !:&lt;br /&gt;
              let colorcat$(cc_html)=&amp;quot;0000FF&amp;quot;&lt;br /&gt;
  25220       write #colorcatfile, using form$(colorcatfile): mat colorcat$,mat colorcat&lt;br /&gt;
  25300    return&lt;br /&gt;
  40000 !&lt;br /&gt;
  40010 Open: ! ***** Function to call library openfile and proc subs&lt;br /&gt;
  40020    def fnOpen(FILENAME$, MAT F$, MAT F, MAT FORM$;INPUTONLY,KEYNUM,___,INDEX)&lt;br /&gt;
  40025       dim _FileIOSubs$(1)*50&lt;br /&gt;
  40030       let fnopen=fnopenfile(FILENAME$, MAT F$, MAT F, MAT FORM$,INPUTONLY,KEYNUM,MAT _FileIOSubs$)&lt;br /&gt;
  40040       for Index=1 to udim(mat _FileIOSubs$) : execute (_FileIOSubs$(Index)) : next Index&lt;br /&gt;
  40090    fnend&lt;br /&gt;
  50000 !&lt;br /&gt;
  60000 Ignore: Continue&lt;br /&gt;
  &lt;br /&gt;
  Color File Layout&lt;br /&gt;
  color.dat, CO_, 1&lt;br /&gt;
  color.key, CODE&lt;br /&gt;
  recl=127&lt;br /&gt;
  ===================================================&lt;br /&gt;
  CODE$,          Color Code,                  C    6&lt;br /&gt;
  NAME$,          English Name for Color,      V   30&lt;br /&gt;
  CATEGORY$,      General Category of Color,   C    6&lt;br /&gt;
  HTML$,          HTML Code for the Color,     C    6&lt;br /&gt;
&lt;br /&gt;
  ColorCat File Layout&lt;br /&gt;
  colorcat.dat, CC_, 0&lt;br /&gt;
  colorcat.key, CODE&lt;br /&gt;
  recl=127&lt;br /&gt;
  ===================================================&lt;br /&gt;
  CODE$,          Category Code,               C    6&lt;br /&gt;
  NAME$,          English Name for Color,      V   30&lt;br /&gt;
  HTML$,          HTML Code for the Color,     C    6&lt;br /&gt;
  &lt;br /&gt;
Example Layout showing multiple keys (price)&lt;br /&gt;
  price.dat, PR_, 0&lt;br /&gt;
  price.key, FARM&lt;br /&gt;
  price.ky2, ITEM&lt;br /&gt;
  price.ky3, FARM/ITEM/GRADE&lt;br /&gt;
  recl=127&lt;br /&gt;
  ===================================================&lt;br /&gt;
  FARM$,          Farm Code (or blank),        C    4&lt;br /&gt;
  ITEM$,          Item Code,                   C    4&lt;br /&gt;
  GRADE$,         Quality,                     C    4&lt;br /&gt;
  X,              Empty,                       X   37&lt;br /&gt;
  PRICE,          Default Price,               BH 3.2&lt;br /&gt;
  COST,           Default Cost,                BH 3.2&lt;br /&gt;
  XOPRICE,        Default Christmas Price,     BH 3.2&lt;br /&gt;
  XOCOST,         Default Christmas Cost,      BH 3.2&lt;br /&gt;
  MOPRICE,        Default Mothers D Price,     BH 3.2&lt;br /&gt;
  MOCOST,         Default Mothers D Cost,      BH 3.2&lt;br /&gt;
  VOPRICE,        Default Valentine Price,     BH 3.2&lt;br /&gt;
  VOCOST,         Default Valentine Cost,      BH 3.2&lt;br /&gt;
&lt;br /&gt;
[[Category:Utilities_Third_Party]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=BR_Web_Scripting_Bridge&amp;diff=3447</id>
		<title>BR Web Scripting Bridge</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=BR_Web_Scripting_Bridge&amp;diff=3447"/>
		<updated>2013-06-19T03:08:24Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;BR Web Scripting Bridge&#039;&#039;&#039; is a [[PHP]] class that has the ability to run BR! programs and display the resulting output on a website. Using the BR Web Scripting Bridge, it is easy to create web interfaces to your BR data, and you don&#039;t have to know a thing about PHP.  Simply drop the BR Web Scripting Bridge and a copy of BR on your web server and start writing your code in BR.&lt;br /&gt;
&lt;br /&gt;
See also:&lt;br /&gt;
*[[HTTP]]&lt;br /&gt;
*[http://brwebscriptingb.sourceforge.net/ SourceForge Project].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== The Method ===&lt;br /&gt;
&lt;br /&gt;
When a page is requested from your web server, your BR code is executed with a bit of PHP script.&lt;br /&gt;
&lt;br /&gt;
To use the BR Web Scripting Bridge, you simply write BR programs that print to standard out. This output is then returned to the web browser.&lt;br /&gt;
&lt;br /&gt;
We created a reusable PHP file that will call a BR program of the same name.  Then you copy the included PHP template file and rename it to match your program name. The php file tells the web server to run your BR program and display the resulting output.&lt;br /&gt;
&lt;br /&gt;
Input to your programs is provided in the form of a set of predefined variables.  These variables contain all data that is sent when a form is submitted by the users web browser.&lt;br /&gt;
&lt;br /&gt;
Using these methods, virtually any web application or http service can be built entirely in BR.  Your pages can utilize any of the technologies currently seen in web pages such as Flash, JavaScript, and AJAX.&lt;br /&gt;
&lt;br /&gt;
=== Requirements ===&lt;br /&gt;
&lt;br /&gt;
*[http://brwebscriptingb.sourceforge.net/ BR Web Scripting Bridge]&lt;br /&gt;
*[http://www.apache.org/ Apache Web Server]&lt;br /&gt;
*[http://www.php.net/ PHP]&lt;br /&gt;
&lt;br /&gt;
=== Examples ===&lt;br /&gt;
Here are some examples of the BR Web Scripting Bridge in action:&lt;br /&gt;
&lt;br /&gt;
*[[#Example 1|Example 1]]: http://www.sageax.com/bridgedemo/adapter.php?BR_SOURCE=src/webcrawl.brs&lt;br /&gt;
*[[#Example 2|Example 2]]: http://www.sageax.com/bridgedemo/adapter.php?BR_SOURCE=src/csscrawl.brs&lt;br /&gt;
*[[#Example 3|Example 3]]: http://www.sageax.com/bridgedemo/adapter.php?BR_SOURCE=src/itemlist.brs&lt;br /&gt;
*[[#Example 4|Example 4]]: http://www.sageax.com/bridgedemo/adapter.php?BR_SOURCE=src/select.brs&lt;br /&gt;
&lt;br /&gt;
Each of the above examples are simple web applications created and controlled by a single BR program.&lt;br /&gt;
&lt;br /&gt;
Each Example consists of a simple three line php file, the BR Web Scripting Bridge, and a single BR program. The .php file is a completely generic .php file. The only thing it does is to find and launch the .br file of the same name. All you have to do is rename it so the name matches the name of your br program.&lt;br /&gt;
&lt;br /&gt;
We named our first example webcrawl, and created a br program called webcrawl to run the example web page.&lt;br /&gt;
The second example is called itemlist, and it and all the others are identical to webcrawl.&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;?PHP&lt;br /&gt;
     include(&#039;class.brphp.php&#039;);&lt;br /&gt;
     $br = new brphp();&lt;br /&gt;
     $br-&amp;gt;RunBrCodeBehind($_SERVER[&#039;PHP_SELF&#039;]);&lt;br /&gt;
  ?&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The generic php code above simply launches the br code below and displays the output in your browser.&lt;br /&gt;
&lt;br /&gt;
====Example 1====&lt;br /&gt;
&lt;br /&gt;
http://www.sageax.com/bridgedemo/webcrawl.php&lt;br /&gt;
&lt;br /&gt;
The above website is created from a simple BR program shown below. This example program uses the [[FileIO Library]] (not shown) to read data out of my data files in my suite of sample programs and sample data. You choose the data file to view from the drop down. When you press the &amp;quot;View File&amp;quot; button, the php server calls BR and returns the results of the file you chose.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  01000  ! WebCrawl - Copyright August 2008 By Gabriel Bakker #Autonumber# 1000,10&lt;br /&gt;
  01010  !&lt;br /&gt;
  01020  ! Created August 4th, 2008&lt;br /&gt;
  01030  !&lt;br /&gt;
  01040  ! This Program Dynamically Generates Html From Your Br Internal Data Files.&lt;br /&gt;
  01050  !&lt;br /&gt;
  01060  ! This Program Requires Fileio To Function And Only Works With Br Internal&lt;br /&gt;
  01070  ! Data Files That Are Described In A Fileio Compatable File Layout Format.&lt;br /&gt;
  01080  !&lt;br /&gt;
  01090  ! This Program Was Designed To Be Called From A Php Web Site, As An Example&lt;br /&gt;
  01100  ! Of The New Ability To Expose Your Br Data To The Web Using These Tools.&lt;br /&gt;
  01110  ! This Program Is An Example Of A Br &amp;quot;CodeBehind&amp;quot; For Php. It Is A Complete&lt;br /&gt;
  01120  ! Br Powered Web Site&lt;br /&gt;
  01130  !&lt;br /&gt;
  01170  !&lt;br /&gt;
  01180  !&lt;br /&gt;
  01190  ! With The BR Web Scripting Bridge Your Program Runs In Response To The User&lt;br /&gt;
  01200  ! Clicking On A Php Web Object Such As A Button. The Button Tells The Php&lt;br /&gt;
  01210  ! To Reload With The Newly Entered Data, And The Php Server Calls Your Br&lt;br /&gt;
  01220  ! Program. Mat _Post$ Contains All The Data The User May Have Entered In&lt;br /&gt;
  01230  ! Your Web Site.&lt;br /&gt;
  01240  !&lt;br /&gt;
  01250  ! You Interpret Mat Post$ And Decide What Needs To Be Done.&lt;br /&gt;
  01260  !&lt;br /&gt;
  01270  ! This Example Is Quite Simple:&lt;br /&gt;
  01280  !&lt;br /&gt;
  01300  !&lt;br /&gt;
  01310     if Trim$(_Post$(1))=&amp;quot;&amp;quot; then ! If The User Did Not Select A File Layout From The List Then&lt;br /&gt;
  01320        let Fnreadlayoutfolder ! Display The File Layout List In A Table&lt;br /&gt;
  01330     else&lt;br /&gt;
  01340        let Fnreadfileio(Trim$(_Post$(1))) ! But If They Did Select A File, Then Show It&lt;br /&gt;
  01350     end if&lt;br /&gt;
  01360  !&lt;br /&gt;
  01370     stop&lt;br /&gt;
  01380  !&lt;br /&gt;
  01390  !&lt;br /&gt;
  01400  !&lt;br /&gt;
  10000  ! #Autonumber# 10000,10&lt;br /&gt;
  10010  READFILEIO: ! ***** Generate Html From Br Internal Data Files&lt;br /&gt;
  10020     def Fnreadfileio(Layoutname$*80;Keynum,Path$*255,_Inputfile,_Index)&lt;br /&gt;
  10030  !&lt;br /&gt;
  10040        dim F$(1)*255, F(1)&lt;br /&gt;
  10050        dim Forms$(1)*255&lt;br /&gt;
  10060        dim Descr$(1)*255, Widths(1)&lt;br /&gt;
  10070  !&lt;br /&gt;
  10080        library &amp;quot;fileio&amp;quot; : Fnopenfile, Fngetfilenumber,Fnreadlayouts&lt;br /&gt;
  10090        dim Directorylist$(1)*255&lt;br /&gt;
  10100  !&lt;br /&gt;
  10110        let Fnreadlayouts(Mat Directorylist$)&lt;br /&gt;
  10120  !&lt;br /&gt;
  10130        let _Inputfile=Fnopen(Layoutname$,Mat F$,Mat F,Mat Forms$,1,Keynum,0,Path$,Mat Descr$)&lt;br /&gt;
  10140        if Udim(Mat Directorylist$) then&lt;br /&gt;
  10150  !&lt;br /&gt;
  10170           print &#039;&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10180           print &#039;&amp;lt;head&amp;gt;&#039;&lt;br /&gt;
  10190           print &#039;&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=iso-8859-1&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  10200           print &#039;&amp;lt;/head&amp;gt;&#039;&lt;br /&gt;
  10210           print &#039;&amp;lt;body&amp;gt;&#039;&lt;br /&gt;
  10220           print &#039;  &amp;lt;form id=&amp;quot;FileData&amp;quot; name=&amp;quot;FileData&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10230           print &#039;    &amp;lt;label&amp;gt;&#039;&lt;br /&gt;
  10240           print &#039;    &amp;lt;p&amp;gt;&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;File Layout:&#039;&lt;br /&gt;
  10250           print &#039;        &amp;lt;select name=&amp;quot;FileLayout&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10260           print &#039;           &amp;lt;option value=&amp;quot;&amp;quot;&amp;gt;All...&amp;lt;/option&amp;gt;&#039;&lt;br /&gt;
  10270           for _Index=1 to Udim(Mat Directorylist$)&lt;br /&gt;
  10280              print &#039;        &amp;lt;option value=&amp;quot;&#039;&lt;br /&gt;
&amp;amp;Trim$(Directorylist$(_Index))&amp;amp;&#039;&amp;quot;&amp;gt;&#039;&amp;amp;Trim$(Directorylist$(_Index))&amp;amp;&#039;&amp;lt;/option&amp;gt;&#039;&lt;br /&gt;
  10290           next _Index&lt;br /&gt;
  10300           print &#039;        &amp;lt;/select&amp;gt;&#039;&lt;br /&gt;
  10310           print &#039;            &amp;lt;p&amp;gt;&amp;lt;input type=&amp;quot;submit&amp;quot; name=&amp;quot;Submit&amp;quot; value=&amp;quot;View File&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  10320           print &#039;    &amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
  10330           print &#039;    &amp;lt;/label&amp;gt;&#039;&lt;br /&gt;
  10340           print &#039;  &amp;lt;/form&amp;gt;&#039;&lt;br /&gt;
  10350  !&lt;br /&gt;
  10360        end if&lt;br /&gt;
  10370  !&lt;br /&gt;
  10380  !&lt;br /&gt;
  10390        if _Inputfile then&lt;br /&gt;
  10400  !&lt;br /&gt;
  10410           print &#039;&amp;lt;title&amp;gt;HTML View for &#039;&amp;amp;Layoutname$&amp;amp;&#039; file.&amp;lt;/title&amp;gt;&#039;&lt;br /&gt;
  10420           print &#039;&amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;&amp;lt;b&amp;gt;HTML View for &#039;&amp;amp;Layoutname$&amp;amp;&#039; file.&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
  10430           print &#039;&#039;&lt;br /&gt;
  10440           print &#039;&amp;lt;table align=&amp;quot;center&amp;quot; border=&amp;quot;1&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10450  !&lt;br /&gt;
  10460           print &#039;  &amp;lt;tr&amp;gt;&#039;&lt;br /&gt;
  10470           for _Index=1 to Udim(Mat Descr$)&lt;br /&gt;
  10480              print &#039;    &amp;lt;th scope=&amp;quot;col&amp;quot;&amp;gt;&#039;&amp;amp;Descr$(_Index)&amp;amp;&#039;&amp;lt;/th&amp;gt;&#039;&lt;br /&gt;
  10490           next _Index&lt;br /&gt;
  10500           print &#039;  &amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
  10510  !&lt;br /&gt;
  10520           do&lt;br /&gt;
  10530              read #_Inputfile, using Forms$(_Inputfile): Mat F$, Mat F eof IGNORE&lt;br /&gt;
  10540              if File(_Inputfile)=0 then ! Read Successful&lt;br /&gt;
  10550                 print &#039;  &amp;lt;tr&amp;gt;&#039;&lt;br /&gt;
  10560                 for _Index=1 to Udim(Mat F$)&lt;br /&gt;
  10570                    print &#039;    &amp;lt;td&amp;gt;&#039;&amp;amp;F$(_Index)&amp;amp;&#039;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
  10580                 next _Index&lt;br /&gt;
  10590                 for _Index=1 to Udim(Mat F)&lt;br /&gt;
  10600                    print &#039;    &amp;lt;td&amp;gt;&#039;&amp;amp;Str$(F(_Index))&amp;amp;&#039;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
  10610                 next _Index&lt;br /&gt;
  10620                 print &#039;  &amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
  10630              end if&lt;br /&gt;
  10640           loop While File(_Inputfile)=0&lt;br /&gt;
  10650  !&lt;br /&gt;
  10660           print &#039;&amp;lt;/table&amp;gt;&#039;&lt;br /&gt;
  10670           print &#039;&amp;lt;/body&amp;gt;&#039;&lt;br /&gt;
  10680           print &#039;&amp;lt;/html&amp;gt;&#039;&lt;br /&gt;
  10690  !&lt;br /&gt;
  10700           close #_Inputfile:&lt;br /&gt;
  10710        end if&lt;br /&gt;
  10720     fnend&lt;br /&gt;
  10730  !&lt;br /&gt;
  11000  ! #Autonumber# 11000,10&lt;br /&gt;
  11010  READLAYOUTFOLDER: ! Generate A Table Listing The Names Of All Your File Layouts&lt;br /&gt;
  11020     def Fnreadlayoutfolder(;_Index)&lt;br /&gt;
  11030  !&lt;br /&gt;
  11040        library &amp;quot;fileio&amp;quot; : Fnreadlayouts, Fngetfilenumber&lt;br /&gt;
  11050        dim Directorylist$(1)*255&lt;br /&gt;
  11060  !&lt;br /&gt;
  11070        let Fnreadlayouts(Mat Directorylist$)&lt;br /&gt;
  11080  !&lt;br /&gt;
  11090        if Udim(Mat Directorylist$) then&lt;br /&gt;
  11100  !&lt;br /&gt;
  11120           print &#039;&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  11130           print &#039;&amp;lt;head&amp;gt;&#039;&lt;br /&gt;
  11140           print &#039;&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=iso-8859-1&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  11150           print &#039;&amp;lt;/head&amp;gt;&#039;&lt;br /&gt;
  11160           print &#039;&amp;lt;body&amp;gt;&#039;&lt;br /&gt;
  11170           print &#039;  &amp;lt;form id=&amp;quot;FileData&amp;quot; name=&amp;quot;FileData&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  11180           print &#039;    &amp;lt;label&amp;gt;&#039;&lt;br /&gt;
  11190           print &#039;    &amp;lt;p&amp;gt;&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;File Layout:&#039;&lt;br /&gt;
  11200           print &#039;        &amp;lt;select name=&amp;quot;FileLayout&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  11210           print &#039;           &amp;lt;option value=&amp;quot;&amp;quot;&amp;gt;All...&amp;lt;/option&amp;gt;&#039;&lt;br /&gt;
  11220           for _Index=1 to Udim(Mat Directorylist$)&lt;br /&gt;
  11230              print &#039;        &amp;lt;option value=&amp;quot;&#039;&amp;amp;&lt;br /&gt;
Trim$(Directorylist$(_Index))&amp;amp;&#039;&amp;quot;&amp;gt;&#039;&amp;amp;Trim$(Directorylist$(_Index))&amp;amp;&#039;&amp;lt;/option&amp;gt;&#039;&lt;br /&gt;
  11240           next _Index&lt;br /&gt;
  11250           print &#039;        &amp;lt;/select&amp;gt;&#039;&lt;br /&gt;
  11260           print &#039;            &amp;lt;p&amp;gt;&amp;lt;input type=&amp;quot;submit&amp;quot; name=&amp;quot;Submit&amp;quot; value=&amp;quot;View File&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  11270           print &#039;    &amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
  11280           print &#039;    &amp;lt;/label&amp;gt;&#039;&lt;br /&gt;
  11290           print &#039;  &amp;lt;/form&amp;gt;&#039;&lt;br /&gt;
  11300           print &#039;  &amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Layout Files&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
  11310           print &#039;&#039;&lt;br /&gt;
  11320           print &#039;  &amp;lt;table align=&amp;quot;center&amp;quot; border=&amp;quot;1&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  11330  !&lt;br /&gt;
  11340           print &#039;    &amp;lt;tr&amp;gt;&#039;&lt;br /&gt;
  11350           print &#039;      &amp;lt;th scope=&amp;quot;col&amp;quot;&amp;gt;Layout&amp;lt;/th&amp;gt;&#039;&lt;br /&gt;
  11360           print &#039;    &amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
  11370  !&lt;br /&gt;
  11380           for _Index=1 to Udim(Mat Directorylist$)&lt;br /&gt;
  11390              print &#039;    &amp;lt;tr&amp;gt;&#039;&lt;br /&gt;
  11400              print &#039;      &amp;lt;td&amp;gt;&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&#039;&amp;amp;Directorylist$(_Index)&amp;amp;&#039;&amp;lt;/div&amp;gt;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
  11410              print &#039;    &amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
  11420           next _Index&lt;br /&gt;
  11430  !&lt;br /&gt;
  11440           print &#039;  &amp;lt;/table&amp;gt;&#039;&lt;br /&gt;
  11450           print &#039;&amp;lt;/body&amp;gt;&#039;&lt;br /&gt;
  11460           print &#039;&amp;lt;/html&amp;gt;&#039;&lt;br /&gt;
  11470  !&lt;br /&gt;
  11480        end if&lt;br /&gt;
  11490     fnend&lt;br /&gt;
  11500  !&lt;br /&gt;
  99000  ! #Autonumber# 99000,10&lt;br /&gt;
  99010  OPEN: ! ***** Function To Call Library Openfile And Proc Subs&lt;br /&gt;
  99020     def Fnopen(Filename$, Mat F$, Mat F, Mat Form$; Inputonly, Keynum, Dont_Sort_Subs, &lt;br /&gt;
Path$*255, Mat Descr$, Mat Field_Widths)&lt;br /&gt;
  99030        let Fnopen=Fnopenfile(Filename$, Mat F$, Mat F, Mat Form$, Inputonly, Keynum, &lt;br /&gt;
Dont_Sort_Subs, Path$, Mat Descr$, Mat Field_Widths)&lt;br /&gt;
  99040        execute (&amp;quot;*proc subs.$$$&amp;quot;)&lt;br /&gt;
  99050     fnend&lt;br /&gt;
  99060  !&lt;br /&gt;
  99980  ! #Autonumber# 99980,10&lt;br /&gt;
  99990  IGNORE: continue&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Example 2====&lt;br /&gt;
&lt;br /&gt;
http://www.sageax.com/bridgedemo/csscrawl.php&lt;br /&gt;
&lt;br /&gt;
Our first example was simple and exciting but the web page didn&#039;t look very nice. For our next example, we&#039;re going to take the same program, and apply a Cascading Style Sheet to make it look a little bit nicer.&lt;br /&gt;
&lt;br /&gt;
Cascading Style Sheets, or CSS files, are replaceable templates that affect the overall look, or style, of a web page. When you design a web site, if you put all your style settings in a CSS file, you can change them all later by simply replacing the CSS file, without having to modify the site itself.&lt;br /&gt;
&lt;br /&gt;
Additionally, you can find many CSS files online that you can just drop into your applications.&lt;br /&gt;
&lt;br /&gt;
For this example, we&#039;ll be taking a CSS file called style.css that contains a bunch of nice styles for tables. We&#039;ll be using it to spruce up the appearance of the tables from the example before.&lt;br /&gt;
&lt;br /&gt;
To use CSS, all we have to do is modify the header to include the style sheet, and modify the tables to use it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  10160 print &#039;&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot; &lt;br /&gt;
&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10170 print &#039;&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10180 print &#039;&amp;lt;head&amp;gt;&#039;&lt;br /&gt;
  10190 print &#039;  &amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=iso-8859-1&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  10200 print &#039;  &amp;lt;link href=&amp;quot;style.css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10210 print &#039;&amp;lt;/head&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In line 10160, we declare the file as an xhtml file as opposed to a regular html file. In line 10200, we include the style sheet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  10450 print &#039;&amp;lt;table id=&amp;quot;hor-minimalist-b&amp;quot; align=&amp;quot;center&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10470 print &#039;  &amp;lt;thead&amp;gt;&#039;&lt;br /&gt;
  10480 print &#039;  &amp;lt;tr&amp;gt;&#039;&lt;br /&gt;
  10490   for _Index=1 to Udim(Mat Descr$)&lt;br /&gt;
  10500     print &#039;    &amp;lt;th scope=&amp;quot;col&amp;quot;&amp;gt;&#039;&amp;amp;Descr$(_Index)&amp;amp;&#039;&amp;lt;/th&amp;gt;&#039;&lt;br /&gt;
  10510   next _Index&lt;br /&gt;
  10520 print &#039;  &amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
  10530 print &#039;  &amp;lt;/thead&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Line 10450 tells the table to use the CSS style &amp;quot;hor-minimalist-b&amp;quot; from the included file.&lt;br /&gt;
&lt;br /&gt;
Notice the &amp;lt;thead&amp;gt; and &amp;lt;/thead&amp;gt; tags above. We also need to specify a &amp;lt;thead&amp;gt; and a &amp;lt;tbody&amp;gt;, so that the style knows what to apply to each part of the table.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  10550 print &#039;  &amp;lt;tbody&amp;gt;&#039;&lt;br /&gt;
  10610 print &#039;    &amp;lt;td&amp;gt;&#039;&amp;amp;F$(_Index)&amp;amp;&#039;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
  10640 print &#039;    &amp;lt;td&amp;gt;&#039;&amp;amp;Str$(F(_Index))&amp;amp;&#039;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
  10700 print &#039;  &amp;lt;/tbody&amp;gt;&#039;&lt;br /&gt;
  10710 print &#039;&amp;lt;/table&amp;gt;&#039;&lt;br /&gt;
  10720 print &#039;&amp;lt;/body&amp;gt;&#039;&lt;br /&gt;
  10730 print &#039;&amp;lt;/html&amp;gt;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We draw the body of the table just like before, adding the &amp;lt;tbody&amp;gt; and &amp;lt;/tbody&amp;gt; tags.&lt;br /&gt;
&lt;br /&gt;
Here is the full example. The code is almost identical to Example 1 but looks a lot nicer when you run it.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  01000  ! CssCrawl - Copyright August 2008 By Gabriel Bakker #Autonumber# 1000,10&lt;br /&gt;
  01010  !&lt;br /&gt;
  01020  ! Created August 4th, 2008&lt;br /&gt;
  01030  !&lt;br /&gt;
  01040  ! This Program Dynamically Generates Html From Your Br Internal Data Files.&lt;br /&gt;
  01050  !&lt;br /&gt;
  01060  ! This Program Requires Fileio To Function And Only Works With Br Internal&lt;br /&gt;
  01070  ! Data Files That Are Described In A Fileio Compatable File Layout Format.&lt;br /&gt;
  01080  !&lt;br /&gt;
  01090  ! This Program Was Designed To Be Called From A Php Web Site, As An Example&lt;br /&gt;
  01100  ! Of The New Ability To Expose Your Br Data To The Web Using These Tools.&lt;br /&gt;
  01110  ! This Program Is An Example Of A Br &amp;quot;CodeBehind&amp;quot; For Php. It Is A Complete&lt;br /&gt;
  01120  ! Br Powered Web Site&lt;br /&gt;
  01130  !&lt;br /&gt;
  01140  ! This Library Is Intended To Be Implemented With The Br Phprun System And&lt;br /&gt;
  01150  ! The Fileio Library.&lt;br /&gt;
  01160  !&lt;br /&gt;
  01170  !&lt;br /&gt;
  01180  !&lt;br /&gt;
  01190  ! With Br Php, Your Program Runs In Response To The User Clicking On&lt;br /&gt;
  01200  ! A Php Web Object Such As A Button. The Button Tells The Php To Reload&lt;br /&gt;
  01210  ! With The Newly Entered Data, And The Php Server Calls Your Br Program.&lt;br /&gt;
  01220  ! Mat _Post$ Contains All The Data The User May Have Entered In Your Web&lt;br /&gt;
  01230  ! Site.&lt;br /&gt;
  01240  !&lt;br /&gt;
  01250  ! You Interpret Mat Post$ And Decide What Needs To Be Done.&lt;br /&gt;
  01260  !&lt;br /&gt;
  01270  ! This Example Is Quite Simple:&lt;br /&gt;
  01280  !&lt;br /&gt;
  01290  !&lt;br /&gt;
  01300     if Trim$(_Post$(1))=&amp;quot;&amp;quot; then ! If The User Did Not Select A File Layout From The List Then&lt;br /&gt;
  01310        let Fnreadlayoutfolder ! Display The File Layout List In A Table&lt;br /&gt;
  01320     else&lt;br /&gt;
  01330        let Fnreadfileio(Trim$(_Post$(1))) ! But If They Did Select A File, Then Show It&lt;br /&gt;
  01340     end if&lt;br /&gt;
  01350  !&lt;br /&gt;
  01360     stop&lt;br /&gt;
  01370  !&lt;br /&gt;
  01380  !&lt;br /&gt;
  01390  !&lt;br /&gt;
  10000  ! #Autonumber# 10000,10&lt;br /&gt;
  10010  READFILEIO: ! ***** Generate Html From Br Internal Data Files&lt;br /&gt;
  10020     def Fnreadfileio(Layoutname$*80;Keynum,Path$*255,_Inputfile,_Index)&lt;br /&gt;
  10030  !&lt;br /&gt;
  10040        dim F$(1)*255, F(1)&lt;br /&gt;
  10050        dim Forms$(1)*255&lt;br /&gt;
  10060        dim Descr$(1)*255, Widths(1)&lt;br /&gt;
  10070  !&lt;br /&gt;
  10080        library &amp;quot;fileio&amp;quot; : Fnopenfile, Fngetfilenumber,Fnreadlayouts&lt;br /&gt;
  10090        dim Directorylist$(1)*255&lt;br /&gt;
  10100  !&lt;br /&gt;
  10110        let Fnreadlayouts(Mat Directorylist$)&lt;br /&gt;
  10120  !&lt;br /&gt;
  10130        let _Inputfile=Fnopen(Layoutname$,Mat F$,Mat F,Mat Forms$,1,Keynum,0,Path$,Mat Descr$)&lt;br /&gt;
  10140        if Udim(Mat Directorylist$) then&lt;br /&gt;
  10150  !&lt;br /&gt;
  10160           print &#039;&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot; &lt;br /&gt;
&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10170           print &#039;&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10180           print &#039;&amp;lt;head&amp;gt;&#039;&lt;br /&gt;
  10190           print &#039;  &amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=iso-8859-1&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  10200           print &#039;  &amp;lt;link href=&amp;quot;style.css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10210           print &#039;&amp;lt;/head&amp;gt;&#039;&lt;br /&gt;
  10220           print &#039;&amp;lt;body&amp;gt;&#039;&lt;br /&gt;
  10230           print &#039;  &amp;lt;form id=&amp;quot;FileData&amp;quot; name=&amp;quot;FileData&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10240           print &#039;    &amp;lt;label&amp;gt;&#039;&lt;br /&gt;
  10250           print &#039;    &amp;lt;p&amp;gt;&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;File Layout:&#039;&lt;br /&gt;
  10260           print &#039;        &amp;lt;select name=&amp;quot;FileLayout&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10270           print &#039;           &amp;lt;option value=&amp;quot;&amp;quot;&amp;gt;All...&amp;lt;/option&amp;gt;&#039;&lt;br /&gt;
  10280           for _Index=1 to Udim(Mat Directorylist$)&lt;br /&gt;
  10290              print &#039;        &amp;lt;option value=&amp;quot;&#039;&amp;amp;&lt;br /&gt;
Trim$(Directorylist$(_Index))&amp;amp;&#039;&amp;quot;&amp;gt;&#039;&amp;amp;Trim$(Directorylist$(_Index))&amp;amp;&#039;&amp;lt;/option&amp;gt;&#039;&lt;br /&gt;
  10300           next _Index&lt;br /&gt;
  10310           print &#039;        &amp;lt;/select&amp;gt;&#039;&lt;br /&gt;
  10320           print &#039;            &amp;lt;p&amp;gt;&amp;lt;input type=&amp;quot;submit&amp;quot; name=&amp;quot;Submit&amp;quot; value=&amp;quot;View File&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  10330           print &#039;    &amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
  10340           print &#039;    &amp;lt;/label&amp;gt;&#039;&lt;br /&gt;
  10350           print &#039;  &amp;lt;/form&amp;gt;&#039;&lt;br /&gt;
  10360  !&lt;br /&gt;
  10370        end if&lt;br /&gt;
  10380  !&lt;br /&gt;
  10390  !&lt;br /&gt;
  10400        if _Inputfile then&lt;br /&gt;
  10410  !&lt;br /&gt;
  10420           print &#039;&amp;lt;title&amp;gt;HTML View for &#039;&amp;amp;Layoutname$&amp;amp;&#039; file.&amp;lt;/title&amp;gt;&#039;&lt;br /&gt;
  10430           print &#039;&amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;&amp;lt;b&amp;gt;HTML View for &#039;&amp;amp;Layoutname$&amp;amp;&#039; file.&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
  10440           print &#039;&#039;&lt;br /&gt;
  10450           print &#039;&amp;lt;table id=&amp;quot;hor-minimalist-b&amp;quot; align=&amp;quot;center&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10460  !&lt;br /&gt;
  10470           print &#039;  &amp;lt;thead&amp;gt;&#039;&lt;br /&gt;
  10480           print &#039;  &amp;lt;tr&amp;gt;&#039;&lt;br /&gt;
  10490           for _Index=1 to Udim(Mat Descr$)&lt;br /&gt;
  10500              print &#039;    &amp;lt;th scope=&amp;quot;col&amp;quot;&amp;gt;&#039;&amp;amp;Descr$(_Index)&amp;amp;&#039;&amp;lt;/th&amp;gt;&#039;&lt;br /&gt;
  10510           next _Index&lt;br /&gt;
  10520           print &#039;  &amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
  10530           print &#039;  &amp;lt;/thead&amp;gt;&#039;&lt;br /&gt;
  10540  !&lt;br /&gt;
  10550           print &#039;  &amp;lt;tbody&amp;gt;&#039;&lt;br /&gt;
  10560           do&lt;br /&gt;
  10570              read #_Inputfile, using Forms$(_Inputfile): Mat F$, Mat F eof IGNORE&lt;br /&gt;
  10580              if File(_Inputfile)=0 then ! Read Successful&lt;br /&gt;
  10590                 print &#039;  &amp;lt;tr&amp;gt;&#039;&lt;br /&gt;
  10600                 for _Index=1 to Udim(Mat F$)&lt;br /&gt;
  10610                    print &#039;    &amp;lt;td&amp;gt;&#039;&amp;amp;F$(_Index)&amp;amp;&#039;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
  10620                 next _Index&lt;br /&gt;
  10630                 for _Index=1 to Udim(Mat F)&lt;br /&gt;
  10640                    print &#039;    &amp;lt;td&amp;gt;&#039;&amp;amp;Str$(F(_Index))&amp;amp;&#039;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
  10650                 next _Index&lt;br /&gt;
  10660                 print &#039;  &amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
  10670              end if&lt;br /&gt;
  10680           loop While File(_Inputfile)=0&lt;br /&gt;
  10690  !&lt;br /&gt;
  10700           print &#039;  &amp;lt;/tbody&amp;gt;&#039;&lt;br /&gt;
  10710           print &#039;&amp;lt;/table&amp;gt;&#039;&lt;br /&gt;
  10720           print &#039;&amp;lt;/body&amp;gt;&#039;&lt;br /&gt;
  10730           print &#039;&amp;lt;/html&amp;gt;&#039;&lt;br /&gt;
  10740  !&lt;br /&gt;
  10750           close #_Inputfile:&lt;br /&gt;
  10760        end if&lt;br /&gt;
  10770     fnend&lt;br /&gt;
  10780  !&lt;br /&gt;
  11000  ! #Autonumber# 11000,10&lt;br /&gt;
  11010  READLAYOUTFOLDER: ! Generate A Table Listing The Names Of All Your File Layouts&lt;br /&gt;
  11020     def Fnreadlayoutfolder(;_Index)&lt;br /&gt;
  11030  !&lt;br /&gt;
  11040        library &amp;quot;fileio&amp;quot; : Fnreadlayouts, Fngetfilenumber&lt;br /&gt;
  11050        dim Directorylist$(1)*255&lt;br /&gt;
  11060  !&lt;br /&gt;
  11070        let Fnreadlayouts(Mat Directorylist$)&lt;br /&gt;
  11080  !&lt;br /&gt;
  11090        if Udim(Mat Directorylist$) then&lt;br /&gt;
  11100  !&lt;br /&gt;
  11110           print &#039;&amp;lt;!DOCTYPE html PUBLIC &amp;quot;-//W3C//DTD XHTML 1.0 Transitional//EN&amp;quot; &lt;br /&gt;
&amp;quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  11120           print &#039;&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  11130           print &#039;&amp;lt;head&amp;gt;&#039;&lt;br /&gt;
  11140           print &#039;  &amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=iso-8859-1&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  11150           print &#039;  &amp;lt;link href=&amp;quot;style.css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  11160           print &#039;&amp;lt;/head&amp;gt;&#039;&lt;br /&gt;
  11170           print &#039;&amp;lt;body&amp;gt;&#039;&lt;br /&gt;
  11180           print &#039;  &amp;lt;form id=&amp;quot;FileData&amp;quot; name=&amp;quot;FileData&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  11190           print &#039;    &amp;lt;label&amp;gt;&#039;&lt;br /&gt;
  11200           print &#039;    &amp;lt;p&amp;gt;&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;File Layout:&#039;&lt;br /&gt;
  11210           print &#039;        &amp;lt;select name=&amp;quot;FileLayout&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  11220           print &#039;           &amp;lt;option value=&amp;quot;&amp;quot;&amp;gt;All...&amp;lt;/option&amp;gt;&#039;&lt;br /&gt;
  11230           for _Index=1 to Udim(Mat Directorylist$)&lt;br /&gt;
  11240              print &#039;        &amp;lt;option value=&amp;quot;&#039;&amp;amp;&lt;br /&gt;
Trim$(Directorylist$(_Index))&amp;amp;&#039;&amp;quot;&amp;gt;&#039;&amp;amp;Trim$(Directorylist$(_Index))&amp;amp;&#039;&amp;lt;/option&amp;gt;&#039;&lt;br /&gt;
  11250           next _Index&lt;br /&gt;
  11260           print &#039;        &amp;lt;/select&amp;gt;&#039;&lt;br /&gt;
  11270           print &#039;            &amp;lt;p&amp;gt;&amp;lt;input type=&amp;quot;submit&amp;quot; name=&amp;quot;Submit&amp;quot; value=&amp;quot;View File&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  11280           print &#039;    &amp;lt;/div&amp;gt;&#039;&lt;br /&gt;
  11290           print &#039;    &amp;lt;/label&amp;gt;&#039;&lt;br /&gt;
  11300           print &#039;  &amp;lt;/form&amp;gt;&#039;&lt;br /&gt;
  11310           print &#039;  &amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Layout Files&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
  11320           print &#039;&#039;&lt;br /&gt;
  11330           print &#039;  &amp;lt;table id=&amp;quot;hor-minimalist-b&amp;quot; align=&amp;quot;center&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  11340  !&lt;br /&gt;
  11350           print &#039;  &amp;lt;thead&amp;gt;&#039;&lt;br /&gt;
  11360           print &#039;    &amp;lt;tr&amp;gt;&#039;&lt;br /&gt;
  11370           print &#039;      &amp;lt;th scope=&amp;quot;col&amp;quot;&amp;gt;Layout&amp;lt;/th&amp;gt;&#039;&lt;br /&gt;
  11380           print &#039;    &amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
  11390           print &#039;  &amp;lt;/thead&amp;gt;&#039;&lt;br /&gt;
  11400  !&lt;br /&gt;
  11410           print &#039;  &amp;lt;tbody&amp;gt;&#039;&lt;br /&gt;
  11420           for _Index=1 to Udim(Mat Directorylist$)&lt;br /&gt;
  11430              print &#039;    &amp;lt;tr&amp;gt;&#039;&lt;br /&gt;
  11440              print &#039;      &amp;lt;td&amp;gt;&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&#039;&amp;amp;Directorylist$(_Index)&amp;amp;&#039;&amp;lt;/div&amp;gt;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
  11450              print &#039;    &amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
  11460           next _Index&lt;br /&gt;
  11470  !&lt;br /&gt;
  11480           print &#039;  &amp;lt;/tbody&amp;gt;&#039;&lt;br /&gt;
  11490           print &#039;  &amp;lt;/table&amp;gt;&#039;&lt;br /&gt;
  11500           print &#039;&amp;lt;/body&amp;gt;&#039;&lt;br /&gt;
  11510           print &#039;&amp;lt;/html&amp;gt;&#039;&lt;br /&gt;
  11520  !&lt;br /&gt;
  11530        end if&lt;br /&gt;
  11540     fnend&lt;br /&gt;
  11550  !&lt;br /&gt;
  99000  ! #Autonumber# 99000,10&lt;br /&gt;
  99010  OPEN: ! ***** Function To Call Library Openfile And Proc Subs&lt;br /&gt;
  99020     def Fnopen(Filename$, Mat F$, Mat F, Mat Form$; Inputonly, Keynum, Dont_Sort_Subs,&lt;br /&gt;
 Path$*255, Mat Descr$, Mat Field_Widths)&lt;br /&gt;
  99030        let Fnopen=Fnopenfile(Filename$, Mat F$, Mat F, Mat Form$, Inputonly, Keynum, &lt;br /&gt;
Dont_Sort_Subs, Path$, Mat Descr$, Mat Field_Widths)&lt;br /&gt;
  99040        execute (&amp;quot;*proc subs.$$$&amp;quot;)&lt;br /&gt;
  99050     fnend&lt;br /&gt;
  99060  !&lt;br /&gt;
  99980  ! #Autonumber# 99980,10&lt;br /&gt;
  99990  IGNORE: continue&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Example 3====&lt;br /&gt;
&lt;br /&gt;
http://www.sageax.com/bridgedemo/itemlist.php&lt;br /&gt;
&lt;br /&gt;
Example 3 demonstrates how to dynamically ask the user for information from your BR program.&lt;br /&gt;
&lt;br /&gt;
This simple BR program reads a list of groceries from the items file and generates a web form where a grocer could order items directly over the internet. The grocer enters quantities in the quantities field for any items he wishes to purchase and presses the &amp;quot;Ok&amp;quot; button when done. The page is submitted again to our program, this time with the MAT _POST$ array populated with all the data the grocer entered into the form. The program processes the data, adding up the quantities and prints out a &amp;quot;Congratulations, your order was successful!&amp;quot; page.&lt;br /&gt;
&lt;br /&gt;
If this were a real life program, you would simply save the new order back into your BR data files.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  10000  ! Itemlist - Copyright August 2008 By Sage Ax #Autonumber# 10000,10&lt;br /&gt;
  10010  !&lt;br /&gt;
  10020  ! Created August 20th, 2008&lt;br /&gt;
  10030  !&lt;br /&gt;
  10040  ! This Program Dynamically Generates Html From Your Br Internal Data Files.&lt;br /&gt;
  10050  !&lt;br /&gt;
  10060  ! This Program Requires Fileio To Function And Only Works With Br Internal&lt;br /&gt;
  10070  ! Data Files That Are Described In A Fileio Compatable File Layout Format.&lt;br /&gt;
  10080  !&lt;br /&gt;
  10090  ! This Program Was Designed To Be Called From A Php Web Site, As An Example&lt;br /&gt;
  10100  ! Of The New Ability To Expose Your Br Data To The Web Using These Tools.&lt;br /&gt;
  10110  ! This Program Is An Example Of A Br &amp;quot;CodeBehind&amp;quot; For Php. It Is A Complete&lt;br /&gt;
  10120  ! Br Powered Web Site&lt;br /&gt;
  10130  !&lt;br /&gt;
  10140  ! This Library Is Intended To Be Implemented With The Br Phprun System And&lt;br /&gt;
  10150  ! The Fileio Library.&lt;br /&gt;
  10160  !&lt;br /&gt;
  10170  !&lt;br /&gt;
  10180  !&lt;br /&gt;
  10190  ! With Br Php, Your Program Runs In Response To The User Clicking On&lt;br /&gt;
  10200  ! A Php Web Object Such As A Button. The Button Tells The Php To Reload&lt;br /&gt;
  10210  ! With The Newly Entered Data, And The Php Server Calls Your Br Program.&lt;br /&gt;
  10220  ! Mat _Post$ Contains All The Data The User May Have Entered In Your Web&lt;br /&gt;
  10230  ! Site.&lt;br /&gt;
  10240  !&lt;br /&gt;
  10250  ! You Interpret Mat Post$ And Decide What Needs To Be Done.&lt;br /&gt;
  10260  !&lt;br /&gt;
  10270  ! This Example Is Quite Simple:&lt;br /&gt;
  10280  !&lt;br /&gt;
  10290  !&lt;br /&gt;
  10300  !&lt;br /&gt;
  10310     dim Subs(4)&lt;br /&gt;
  10320     dim Subn(3)&lt;br /&gt;
  10330     dim Item$(1)*255, Item(1)&lt;br /&gt;
  10340     dim Forms$(1)*255&lt;br /&gt;
  10350     dim Descr$(1)*255, Widths(1)&lt;br /&gt;
  10360  !&lt;br /&gt;
  10370     if udim(_post$)&amp;gt;10 then goto DisplayResults&lt;br /&gt;
  10380  !&lt;br /&gt;
  10390     library &amp;quot;fileio&amp;quot; : Fnopenfile, Fngetfilenumber&lt;br /&gt;
  10400  !&lt;br /&gt;
  10410     let _Inputfile=Fnopen(&amp;quot;opditem&amp;quot;,Mat Item$,Mat Item,Mat Forms$,1,0,0,&amp;quot;&amp;quot;,Mat Descr$)&lt;br /&gt;
  10420  !&lt;br /&gt;
  10430     let Subs(1)=It_Item&lt;br /&gt;
  10440     let Subs(2)=It_Desc&lt;br /&gt;
  10450     let Subs(3)=It_Um&lt;br /&gt;
  10460     let Subs(4)=It_Size&lt;br /&gt;
  10470     let Subn(1)=It_Cost&lt;br /&gt;
  10480     let Subn(2)=It_Price&lt;br /&gt;
  10490     let Subn(3)=It_Retail&lt;br /&gt;
  10500  !&lt;br /&gt;
  10510     if _Inputfile then&lt;br /&gt;
  10520  !&lt;br /&gt;
  10540        print &#039;&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10550        print &#039;&amp;lt;head&amp;gt;&#039;&lt;br /&gt;
  10560        print &#039;&amp;lt;title&amp;gt;Sample Order Entry&amp;lt;/title&amp;gt;&#039;&lt;br /&gt;
  10570        print &#039;&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=iso-8859-1&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  10580        print &#039;&amp;lt;/head&amp;gt;&#039;&lt;br /&gt;
  10590        print &#039;&amp;lt;body&amp;gt;&#039;&lt;br /&gt;
  10600        print &#039;&amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;&amp;lt;b&amp;gt;Sample Order Entry&amp;lt;/b&amp;gt;&amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
  10610        print &#039;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
  10620        print &#039;&amp;lt;form id=&amp;quot;FileData&amp;quot; name=&amp;quot;FileData&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10630        print &#039;&amp;lt;table align=&amp;quot;center&amp;quot; border=&amp;quot;1&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10640        print &#039;  &amp;lt;tr&amp;gt;&#039;&lt;br /&gt;
  10650        print &#039;    &amp;lt;th scope=&amp;quot;col&amp;quot;&amp;gt;Qty Ordered&amp;lt;/th&amp;gt;&#039;&lt;br /&gt;
  10660        for _Index=1 to Udim(Mat Subs) ! Print String Captions&lt;br /&gt;
  10670           print &#039;    &amp;lt;th scope=&amp;quot;col&amp;quot;&amp;gt;&#039;&amp;amp;Descr$(Subs(_Index))&amp;amp;&#039;&amp;lt;/th&amp;gt;&#039;&lt;br /&gt;
  10680        next _Index&lt;br /&gt;
  10690        for _Index=1 to Udim(Mat Subn) ! Print Numeric Captions&lt;br /&gt;
  10700           print &#039;    &amp;lt;th scope=&amp;quot;col&amp;quot;&amp;gt;&#039;&amp;amp;Descr$(Subn(_Index)+Udim(Mat Item$))&amp;amp;&#039;&amp;lt;/th&amp;gt;&#039;&lt;br /&gt;
  10710        next _Index&lt;br /&gt;
  10720        print &#039;  &amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
  10730  !&lt;br /&gt;
  10740        do&lt;br /&gt;
  10750           read #_Inputfile, using Forms$(_Inputfile): Mat Item$, Mat Item eof IGNORE&lt;br /&gt;
  10760  !&lt;br /&gt;
  10770           if File(_Inputfile)=0 then ! Read Successful&lt;br /&gt;
  10780              print &#039;  &amp;lt;tr&amp;gt;&#039;&lt;br /&gt;
  10790              print &#039;    &amp;lt;td&amp;gt;&amp;lt;label&amp;gt;&#039;&lt;br /&gt;
  10800              print &#039;    Qty: &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;Qty&#039;&amp;amp;&lt;br /&gt;
Item$(It_Item)&amp;amp;&#039;&amp;quot; id=&amp;quot;Qty&#039;&amp;amp;Item$(It_Item)&amp;amp;&#039;&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  10810              print &#039;    &amp;lt;/label&amp;gt;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
  10820              for _Index=1 to Udim(Mat Subs)&lt;br /&gt;
  10830                 print &#039;    &amp;lt;td&amp;gt;&#039;&amp;amp;Item$(Subs(_Index))&amp;amp;&#039;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
  10840              next _Index&lt;br /&gt;
  10850              for _Index=1 to Udim(Mat Subn)&lt;br /&gt;
  10860                 print &#039;    &amp;lt;td&amp;gt;&#039;&amp;amp;Str$(Item(Subn(_Index)))&amp;amp;&#039;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
  10870              next _Index&lt;br /&gt;
  10880              print &#039;  &amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
  10890           end if&lt;br /&gt;
  10900        loop While File(_Inputfile)=0&lt;br /&gt;
  10910  !&lt;br /&gt;
  10920        print &#039;&amp;lt;/table&amp;gt;&#039;&lt;br /&gt;
  10930  !&lt;br /&gt;
  10940        print &#039;&amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;&amp;lt;label&amp;gt;Submit Order: &amp;lt;input type=&amp;quot;submit&amp;quot; name=&amp;quot;button&amp;quot; &lt;br /&gt;
id=&amp;quot;cow&amp;quot; value=&amp;quot;Ok&amp;quot; /&amp;gt;&amp;lt;/label&amp;gt;&amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
  10950  !&lt;br /&gt;
  10960        print &#039;&amp;lt;/form&amp;gt;&#039;&lt;br /&gt;
  10970        print &#039;&amp;lt;/body&amp;gt;&#039;&lt;br /&gt;
  10980        print &#039;&amp;lt;/html&amp;gt;&#039;&lt;br /&gt;
  10990  !&lt;br /&gt;
  11000        close #_Inputfile:&lt;br /&gt;
  11010     end if&lt;br /&gt;
  11020  !&lt;br /&gt;
  11030     Goto EndProgram&lt;br /&gt;
  11040  !&lt;br /&gt;
  11050     DisplayResults: ! Display results&lt;br /&gt;
  11060  !&lt;br /&gt;
  11070        For Index=1 to udim(mat _post$)&lt;br /&gt;
  11080          if Index&amp;lt;&amp;gt;p_button then&lt;br /&gt;
  11090             TotalQty+=val(_post$(Index)) conv Ignore&lt;br /&gt;
  11100          end if&lt;br /&gt;
  11110        next Index&lt;br /&gt;
  11120  !&lt;br /&gt;
  11130        print &#039;...........&#039; ! Extra spaces in case of parsing differences&lt;br /&gt;
  11140        print &#039;&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  11150        print &#039;&amp;lt;head&amp;gt;&#039;&lt;br /&gt;
  11160        print &#039;&amp;lt;title&amp;gt;Order Submitted!&amp;lt;/title&amp;gt;&#039;&lt;br /&gt;
  11170        print &#039;&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=iso-8859-1&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  11180        print &#039;&amp;lt;/head&amp;gt;&#039;&lt;br /&gt;
  11190        print &#039;&amp;lt;body&amp;gt;&#039;&lt;br /&gt;
  11200        print &#039;&amp;lt;b&amp;gt;&amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;Congratulations!!!&amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
  11210        print &#039;&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
  11220        print &#039;&amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;Your order for &#039;&amp;amp;str$(TotalQty)&amp;amp;&#039; items has been recieved.&#039;&lt;br /&gt;
  11230        print &#039;&amp;lt;/body&amp;gt;&#039;&lt;br /&gt;
  11240        print &#039;&amp;lt;/html&amp;gt;&#039;&lt;br /&gt;
  11250  !&lt;br /&gt;
  11260     EndProgram: ! End program&lt;br /&gt;
  11270     stop&lt;br /&gt;
  11280  !&lt;br /&gt;
  11290  !&lt;br /&gt;
  99000  ! #Autonumber# 99000,10&lt;br /&gt;
  99010  OPEN: ! ***** Function To Call Library Openfile And Proc Subs&lt;br /&gt;
  99020     def Fnopen(Filename$, Mat F$, Mat F, Mat Form$; Inputonly, Keynum, Dont_Sort_Subs, &lt;br /&gt;
Path$*255, Mat Descr$, Mat Field_Widths)&lt;br /&gt;
  99030        let Fnopen=Fnopenfile(Filename$, Mat F$, Mat F, Mat Form$, Inputonly, Keynum, &lt;br /&gt;
Dont_Sort_Subs, Path$, Mat Descr$, Mat Field_Widths)&lt;br /&gt;
  99040        execute (&amp;quot;*proc subs.$$$&amp;quot;)&lt;br /&gt;
  99050     fnend&lt;br /&gt;
  99060  !&lt;br /&gt;
  99980  ! #Autonumber# 99980,10&lt;br /&gt;
  99990  IGNORE: continue&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Example 4====&lt;br /&gt;
&lt;br /&gt;
http://www.sageax.com/bridgedemo/select.php&lt;br /&gt;
&lt;br /&gt;
Our next example demonstrates both data entry and multi-program applications.&lt;br /&gt;
&lt;br /&gt;
This example is in three parts, each controlled by a separate BR program.&lt;br /&gt;
&lt;br /&gt;
The first br program and php file are called &amp;quot;select&amp;quot;. This BR program simply displays the contents of the colorcat file and ask&#039;s a user to select a record from it using radio buttons.&lt;br /&gt;
&lt;br /&gt;
The second BR program and php file are called &amp;quot;edit&amp;quot;. This BR program presents the contents of the record the user selected, allowing the user to edit them in a web form.&lt;br /&gt;
&lt;br /&gt;
The third BR program and PHP file are called &amp;quot;save&amp;quot;. This BR program saves the changes the user made and prints a confirmation message.&lt;br /&gt;
&lt;br /&gt;
select.brs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  10000  ! Select - Copyright August 2008 By Sage Ax #Autonumber# 10000,10&lt;br /&gt;
  10010  !&lt;br /&gt;
  10020  ! Created August 21st, 2008&lt;br /&gt;
  10030  !&lt;br /&gt;
  10040  ! This Program Dynamically Generates Html From Your Br Internal Data Files.&lt;br /&gt;
  10050  !&lt;br /&gt;
  10060  ! This Program Requires Fileio To Function And Only Works With Br Internal&lt;br /&gt;
  10070  ! Data Files That Are Described In A Fileio Compatable File Layout Format.&lt;br /&gt;
  10080  !&lt;br /&gt;
  10090  ! This Program Was Designed To Be Called From A Php Web Site, As An Example&lt;br /&gt;
  10100  ! Of The New Ability To Expose Your Br Data To The Web Using These Tools.&lt;br /&gt;
  10110  ! This Program Is An Example Of A Br &amp;quot;CodeBehind&amp;quot; For Php. It Is A Complete&lt;br /&gt;
  10120  ! Br Powered Web Site&lt;br /&gt;
  10130  !&lt;br /&gt;
  10140  ! This Library Is Intended To Be Implemented With The Br Phprun System And&lt;br /&gt;
  10150  ! The Fileio Library.&lt;br /&gt;
  10160  !&lt;br /&gt;
  10170  !&lt;br /&gt;
  10180  !&lt;br /&gt;
  10190  ! This Program Is The First Part In A Three Part Demonstration Showing How&lt;br /&gt;
  10200  ! You Can Use A Seperate Program For Each &amp;quot;Step&amp;quot; In The Process.&lt;br /&gt;
  10210  !&lt;br /&gt;
  10220  ! In This Stage In The Process, The User Is Presented With A Selection Screen&lt;br /&gt;
  10230  ! On Which They Can Select A Colorcat Record To Edit. We&#039;ll also show the&lt;br /&gt;
  10240  ! Entire Contents Of The Colorcat File On The Screen For Review.&lt;br /&gt;
  10250  !&lt;br /&gt;
  10260  !&lt;br /&gt;
  10270     dim Colorcat$(1)*255, Colorcat(1)&lt;br /&gt;
  10280     dim Forms$(1)*255&lt;br /&gt;
  10290     dim Descr$(1)*255, Widths(1)&lt;br /&gt;
  10300  !&lt;br /&gt;
  10310     library &amp;quot;fileio&amp;quot; : Fnopenfile, Fngetfilenumber&lt;br /&gt;
  10320  !&lt;br /&gt;
  10330     let _Inputfile=Fnopen(&amp;quot;colorcat&amp;quot;,Mat Colorcat$,Mat Colorcat,Mat Forms$,1,0,0,&amp;quot;&amp;quot;,Mat Descr$)&lt;br /&gt;
  10340  !&lt;br /&gt;
  10360     print &#039;&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10370     print &#039;&amp;lt;head&amp;gt;&#039;&lt;br /&gt;
  10380     print &#039;&amp;lt;title&amp;gt;Select a record&amp;lt;/title&amp;gt;&#039;&lt;br /&gt;
  10390     print &#039;&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=iso-8859-1&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  10400     print &#039;&amp;lt;/head&amp;gt;&#039;&lt;br /&gt;
  10410     print &#039;&amp;lt;body&amp;gt;&#039;&lt;br /&gt;
  10420     print &#039;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
  10430     print &#039;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
  10440     print &#039;&amp;lt;form id=&amp;quot;Colorcat&amp;quot; name=&amp;quot;colorcat&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;edit.php&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10450  !&lt;br /&gt;
  10460     print &#039;  &amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;Select a record and press Edit.&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
  10470     print &#039;    &amp;lt;input type=&amp;quot;submit&amp;quot; name=&amp;quot;button&amp;quot; value=&amp;quot;Edit&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  10480     print &#039;  &amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
  10490  !&lt;br /&gt;
  10500     print &#039;&amp;lt;table align=&amp;quot;center&amp;quot; border=&amp;quot;1&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10510     print &#039;  &amp;lt;tr&amp;gt;&#039;&lt;br /&gt;
  10520     print &#039;    &amp;lt;th scope=&amp;quot;col&amp;quot;&amp;gt;Select&amp;lt;/th&amp;gt;&#039;&lt;br /&gt;
  10530     for _Index=1 to Udim(Mat Descr$) ! Print String Captions&lt;br /&gt;
  10540        print &#039;    &amp;lt;th scope=&amp;quot;col&amp;quot;&amp;gt;&#039;&amp;amp;Descr$(_Index)&amp;amp;&#039;&amp;lt;/th&amp;gt;&#039;&lt;br /&gt;
  10550     next _Index&lt;br /&gt;
  10560     print &#039;  &amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
  10570  !&lt;br /&gt;
  10580     do&lt;br /&gt;
  10590        read #_Inputfile, using Forms$(_Inputfile): Mat Colorcat$, Mat Colorcat eof IGNORE&lt;br /&gt;
  10600        if File(_Inputfile)=0 then ! Read Successful&lt;br /&gt;
  10610           print &#039;  &amp;lt;tr bgcolor=&amp;quot;&#039;&amp;amp;Colorcat$(Cc_Html)&amp;amp;&#039;&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10620           print &#039;&amp;lt;td&amp;gt; &amp;lt;input name=&amp;quot;key&amp;quot; type=&amp;quot;radio&amp;quot; value=&amp;quot;&#039;&amp;amp;Colorcat$(Cc_Code)&amp;amp;&#039;&amp;quot; /&amp;gt;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
  10630           for _Index=1 to Udim(Mat Colorcat$)&lt;br /&gt;
  10640              print &#039;    &amp;lt;td&amp;gt;&#039;&amp;amp;Colorcat$(_Index)&amp;amp;&#039;&amp;lt;/td&amp;gt;&#039;&lt;br /&gt;
  10650           next _Index&lt;br /&gt;
  10660           print &#039;  &amp;lt;/tr&amp;gt;&#039;&lt;br /&gt;
  10670        end if&lt;br /&gt;
  10680     loop While File(_Inputfile)=0&lt;br /&gt;
  10690  !&lt;br /&gt;
  10700     print &#039;&amp;lt;/table&amp;gt;&#039;&lt;br /&gt;
  10710  !&lt;br /&gt;
  10720     print &#039;&amp;lt;/form&amp;gt;&#039;&lt;br /&gt;
  10730     print &#039;&amp;lt;/body&amp;gt;&#039;&lt;br /&gt;
  10740     print &#039;&amp;lt;/html&amp;gt;&#039;&lt;br /&gt;
  10750  !&lt;br /&gt;
  10760     close #_Inputfile:&lt;br /&gt;
  10770  !&lt;br /&gt;
  10780     stop&lt;br /&gt;
  10790  !&lt;br /&gt;
  10800  !&lt;br /&gt;
  99000  ! #Autonumber# 99000,10&lt;br /&gt;
  99010  OPEN: ! ***** Function To Call Library Openfile And Proc Subs&lt;br /&gt;
  99020     def Fnopen(Filename$, Mat F$, Mat F, Mat Form$; Inputonly, Keynum, Dont_Sort_Subs,&lt;br /&gt;
Path$*255, Mat Descr$, Mat Field_Widths)&lt;br /&gt;
  99030        let Fnopen=Fnopenfile(Filename$, Mat F$, Mat F, Mat Form$, Inputonly, Keynum, &lt;br /&gt;
Dont_Sort_Subs, Path$, Mat Descr$, Mat Field_Widths)&lt;br /&gt;
  99040        execute (&amp;quot;*proc subs.$$$&amp;quot;)&lt;br /&gt;
  99050     fnend&lt;br /&gt;
  99060  !&lt;br /&gt;
  99980  ! #Autonumber# 99980,10&lt;br /&gt;
  99990  IGNORE: continue&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
edit.brs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  10000  ! Edit - Copyright August 2008 By Sage Ax #Autonumber# 10000,10&lt;br /&gt;
  10010  !&lt;br /&gt;
  10020  ! Created August 21st, 2008&lt;br /&gt;
  10030  !&lt;br /&gt;
  10040  !&lt;br /&gt;
  10050  ! This Program Is The Second Part In A Three Part Demonstration Showing How&lt;br /&gt;
  10060  ! You Can Use A Seperate Program For Each &amp;quot;Step&amp;quot; In The Process.&lt;br /&gt;
  10070  !&lt;br /&gt;
  10080  ! In This Stage In The Process, The User Is Presented With The Data For&lt;br /&gt;
  10090  ! A Colorcat Record So That They Can Change It And Save It.&lt;br /&gt;
  10100  !&lt;br /&gt;
  10110  !&lt;br /&gt;
  10120     dim Colorcat$(1)*255, Colorcat(1)&lt;br /&gt;
  10130     dim Forms$(1)*255&lt;br /&gt;
  10140     dim Descr$(1)*255, Widths(1)&lt;br /&gt;
  10150  !&lt;br /&gt;
  10160     library &amp;quot;fileio&amp;quot; : Fnopenfile, Fngetfilenumber&lt;br /&gt;
  10170  !&lt;br /&gt;
  10180     if P_Key then&lt;br /&gt;
  10190        let _Inputfile=Fnopen(&amp;quot;colorcat&amp;quot;,Mat Colorcat$,Mat Colorcat,Mat Forms$,1,0,0,&amp;quot;&amp;quot;,&lt;br /&gt;
Mat Descr$)&lt;br /&gt;
  10200        if _Inputfile then&lt;br /&gt;
  10210           read #_Inputfile, using Forms$(_Inputfile), key=_Post$(P_Key) : Mat Colorcat$, &lt;br /&gt;
Mat Colorcat nokey IGNORE&lt;br /&gt;
  10220           close #_Inputfile:&lt;br /&gt;
  10230        end if&lt;br /&gt;
  10240     end if&lt;br /&gt;
  10250  !&lt;br /&gt;
  10260  !&lt;br /&gt;
  10270     if Cc_Code=0 Or Trim$(Colorcat$(Cc_Code))=&amp;quot;&amp;quot; then ! If Record Not Found&lt;br /&gt;
  10280  !&lt;br /&gt;
  10290        print &#039;............&#039;&lt;br /&gt;
  10300        print &#039;&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10310        print &#039;&amp;lt;head&amp;gt;&#039;&lt;br /&gt;
  10320        print &#039;&amp;lt;title&amp;gt;Error&amp;lt;/title&amp;gt;&#039;&lt;br /&gt;
  10330        print &#039;&amp;lt;meta http-equiv=&amp;quot;REFRESH&amp;quot; content=&amp;quot;4;url=select.php&amp;quot;/&amp;gt;&#039;&lt;br /&gt;
  10340        print &#039;&amp;lt;/head&amp;gt;&#039;&lt;br /&gt;
  10350        print &#039;&amp;lt;body&amp;gt;&#039;&lt;br /&gt;
  10360        print &#039;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
  10370        if P_Key=0 then&lt;br /&gt;
  10380           print &#039;&amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;Please select a record and &amp;lt;A HREF=&amp;quot;select.php&amp;quot;&amp;gt;&lt;br /&gt;
try again&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
  10390        else&lt;br /&gt;
  10400           print &#039;&amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;The record could not be found. Please &amp;lt;A HREF=&amp;quot;select.php&amp;quot;&amp;gt;&lt;br /&gt;
try again&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
  10410        end if&lt;br /&gt;
  10420        print &#039;&amp;lt;/body&amp;gt;&#039;&lt;br /&gt;
  10430        print &#039;&amp;lt;/html&amp;gt;&#039;&lt;br /&gt;
  10440  !&lt;br /&gt;
  10450        stop&lt;br /&gt;
  10460  !&lt;br /&gt;
  10470     end if&lt;br /&gt;
  10480  !&lt;br /&gt;
  10490     print &#039;&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10500     print &#039;&amp;lt;head&amp;gt;&#039;&lt;br /&gt;
  10510     print &#039;&amp;lt;title&amp;gt;Edit the record&amp;lt;/title&amp;gt;&#039;&lt;br /&gt;
  10520     print &#039;&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=iso-8859-1&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  10530     print &#039;&amp;lt;/head&amp;gt;&#039;&lt;br /&gt;
  10540     print &#039;&amp;lt;body&amp;gt;&#039;&lt;br /&gt;
  10550     print &#039;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
  10560     print &#039;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
  10570     print &#039;&amp;lt;form id=&amp;quot;Colorcat&amp;quot; name=&amp;quot;colorcat&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;save.php&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10580     print &#039;  &amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;Edit the data and press Save.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
  10590     print &#039;  Key: &#039;&amp;amp;Colorcat$(Cc_Code)&amp;amp;&#039;&amp;lt;input type=&amp;quot;hidden&amp;quot; name=&amp;quot;key&amp;quot;  value=&amp;quot;&#039;&amp;amp;&lt;br /&gt;
Colorcat$(Cc_Code)&amp;amp;&#039;&amp;quot;/&amp;gt;&#039;&lt;br /&gt;
  10600     print &#039;  Description: &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;Description&amp;quot; value=&amp;quot;&#039;&amp;amp;Colorcat$(Cc_Name)&lt;br /&gt;
&amp;amp;&#039;&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  10610     print &#039;  Color: &amp;lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;Color&amp;quot; value=&amp;quot;&#039;&amp;amp;Colorcat$(Cc_Html)&amp;amp;&#039;&amp;quot; /&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
  10620     print &#039;    &amp;lt;br&amp;gt;&amp;lt;input type=&amp;quot;submit&amp;quot; name=&amp;quot;button&amp;quot; value=&amp;quot;Save&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  10630     print &#039;  &amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
  10640     print &#039;&amp;lt;/form&amp;gt;&#039;&lt;br /&gt;
  10650     print &#039;&amp;lt;/body&amp;gt;&#039;&lt;br /&gt;
  10660     print &#039;&amp;lt;/html&amp;gt;&#039;&lt;br /&gt;
  10670  !&lt;br /&gt;
  10680     stop&lt;br /&gt;
  10690  !&lt;br /&gt;
  10700  !&lt;br /&gt;
  99000  ! #Autonumber# 99000,10&lt;br /&gt;
  99010  OPEN: ! ***** Function To Call Library Openfile And Proc Subs&lt;br /&gt;
  99020     def Fnopen(Filename$, Mat F$, Mat F, Mat Form$; Inputonly, Keynum, Dont_Sort_Subs, &lt;br /&gt;
Path$*255, Mat Descr$, Mat Field_Widths)&lt;br /&gt;
  99030        let Fnopen=Fnopenfile(Filename$, Mat F$, Mat F, Mat Form$, Inputonly, Keynum, &lt;br /&gt;
Dont_Sort_Subs, Path$, Mat Descr$, Mat Field_Widths)&lt;br /&gt;
  99040        execute (&amp;quot;*proc subs.$$$&amp;quot;)&lt;br /&gt;
  99050     fnend&lt;br /&gt;
  99060  !&lt;br /&gt;
  99980  ! #Autonumber# 99980,10&lt;br /&gt;
  99990  IGNORE: continue&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
save.br:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  10000  ! Save - Copyright August 2008 By Sage Ax #Autonumber# 10000,10&lt;br /&gt;
  10010  !&lt;br /&gt;
  10020  ! Created August 21st, 2008&lt;br /&gt;
  10030  !&lt;br /&gt;
  10040  !&lt;br /&gt;
  10050  ! This Program Is The Second Part In A Three Part Demonstration Showing How&lt;br /&gt;
  10060  ! You Can Use A Seperate Program For Each &amp;quot;Step&amp;quot; In The Process.&lt;br /&gt;
  10070  !&lt;br /&gt;
  10080  ! In This Stage In The Process, The data is saved and a confirmation is printed.&lt;br /&gt;
  10100  !&lt;br /&gt;
  10110  !&lt;br /&gt;
  10120     dim Colorcat$(1)*255, Colorcat(1)&lt;br /&gt;
  10130     dim Forms$(1)*255&lt;br /&gt;
  10150  !&lt;br /&gt;
  10160     library &amp;quot;fileio&amp;quot; : Fnopenfile, Fngetfilenumber&lt;br /&gt;
  10170     print Mat _Post$&lt;br /&gt;
  10180  !&lt;br /&gt;
  10190     if P_Key then&lt;br /&gt;
  10200        let _Inputfile=Fnopen(&amp;quot;colorcat&amp;quot;,Mat Colorcat$,Mat Colorcat,Mat Forms$)&lt;br /&gt;
  10210        if _Inputfile then&lt;br /&gt;
  10220           read #_Inputfile, using Forms$(_Inputfile), key=_Post$(P_Key) : Mat Colorcat$, &lt;br /&gt;
Mat Colorcat nokey IGNORE&lt;br /&gt;
  10230           let Colorcat$(cc_code)=_post$(p_key)&lt;br /&gt;
  10240           let Colorcat$(cc_name)=_post$(p_description)&lt;br /&gt;
  10250           let Colorcat$(cc_html)=_post$(p_color)&lt;br /&gt;
  10260           rewrite #_Inputfile, using forms$(_Inputfile) : mat colorcat$, mat colorcat&lt;br /&gt;
  10270           let found=1&lt;br /&gt;
  10280        end if&lt;br /&gt;
  10290     end if&lt;br /&gt;
  10300  !&lt;br /&gt;
  10310     if not found then ! If Record Not Found&lt;br /&gt;
  10320  !&lt;br /&gt;
  10330        print &#039;............&#039;&lt;br /&gt;
  10340        print &#039;&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10350        print &#039;&amp;lt;head&amp;gt;&#039;&lt;br /&gt;
  10360        print &#039;&amp;lt;title&amp;gt;Error&amp;lt;/title&amp;gt;&#039;&lt;br /&gt;
  10370        print &#039;&amp;lt;meta http-equiv=&amp;quot;REFRESH&amp;quot; content=&amp;quot;4;url=select.php&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10380        print &#039;&amp;lt;/head&amp;gt;&#039;&lt;br /&gt;
  10390        print &#039;&amp;lt;body&amp;gt;&#039;&lt;br /&gt;
  10400        print &#039;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
  10410        print &#039;&amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;The record could not be found. Please &amp;lt;A HREF=&amp;quot;select.php&amp;quot;&amp;gt;&lt;br /&gt;
try again&amp;lt;/a&amp;gt;.&amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
  10420        print &#039;&amp;lt;/body&amp;gt;&#039;&lt;br /&gt;
  10430        print &#039;&amp;lt;/html&amp;gt;&#039;&lt;br /&gt;
  10440  !&lt;br /&gt;
  10450        stop&lt;br /&gt;
  10460  !&lt;br /&gt;
  10470     end if&lt;br /&gt;
  10480  !&lt;br /&gt;
  10485     PRINT &amp;quot;########[BEGINHTML]########.................&amp;quot;&lt;br /&gt;
  10490     print &#039;&amp;lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10500     print &#039;&amp;lt;head&amp;gt;&#039;&lt;br /&gt;
  10510     print &#039;&amp;lt;title&amp;gt;Success&amp;lt;/title&amp;gt;&#039;&lt;br /&gt;
  10520     print &#039;&amp;lt;meta http-equiv=&amp;quot;Content-Type&amp;quot; content=&amp;quot;text/html; charset=iso-8859-1&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  10530     print &#039;&amp;lt;/head&amp;gt;&#039;&lt;br /&gt;
  10540     print &#039;&amp;lt;body&amp;gt;&#039;&lt;br /&gt;
  10550     print &#039;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
  10560     print &#039;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
  10570     print &#039;&amp;lt;form id=&amp;quot;Colorcat&amp;quot; name=&amp;quot;colorcat&amp;quot; method=&amp;quot;post&amp;quot; action=&amp;quot;select.php&amp;quot;&amp;gt;&#039;&lt;br /&gt;
  10580     print &#039;  &amp;lt;p align=&amp;quot;center&amp;quot;&amp;gt;Your record has been saved!&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&#039;&lt;br /&gt;
  10590     print &#039;    &amp;lt;input type=&amp;quot;submit&amp;quot; name=&amp;quot;button&amp;quot; value=&amp;quot;Show Me&amp;quot; /&amp;gt;&#039;&lt;br /&gt;
  10600     print &#039;  &amp;lt;/p&amp;gt;&#039;&lt;br /&gt;
  10610     print &#039;&amp;lt;/form&amp;gt;&#039;&lt;br /&gt;
  10620     print &#039;&amp;lt;/body&amp;gt;&#039;&lt;br /&gt;
  10630     print &#039;&amp;lt;/html&amp;gt;&#039;&lt;br /&gt;
  10640  !&lt;br /&gt;
  10650     stop&lt;br /&gt;
  10660  !&lt;br /&gt;
  10670  !&lt;br /&gt;
  99000  ! #Autonumber# 99000,10&lt;br /&gt;
  99010  OPEN: ! ***** Function To Call Library Openfile And Proc Subs&lt;br /&gt;
  99020     def Fnopen(Filename$, Mat F$, Mat F, Mat Form$; Inputonly, Keynum, Dont_Sort_Subs, &lt;br /&gt;
Path$*255, Mat Descr$, Mat Field_Widths)&lt;br /&gt;
  99030        let Fnopen=Fnopenfile(Filename$, Mat F$, Mat F, Mat Form$, Inputonly, Keynum, &lt;br /&gt;
Dont_Sort_Subs, Path$, Mat Descr$, Mat Field_Widths)&lt;br /&gt;
  99040        execute (&amp;quot;*proc subs.$$$&amp;quot;)&lt;br /&gt;
  99050     fnend&lt;br /&gt;
  99060  !&lt;br /&gt;
  99980  ! #Autonumber# 99980,10&lt;br /&gt;
  99990  IGNORE: continue&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== User Guide ===&lt;br /&gt;
&lt;br /&gt;
This page will be updated with the documentation as soon as it is released.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Third Party Utilities]]&lt;br /&gt;
[[Category:Open Source]]&lt;br /&gt;
[[Category:HTTP]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=BRS2BR&amp;diff=3445</id>
		<title>BRS2BR</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=BRS2BR&amp;diff=3445"/>
		<updated>2013-06-19T03:08:23Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Purpose: A utility to enable the windows explorer right click menu to convert a .BRS or .WBS file to the .BR or .WB format.&lt;br /&gt;
&lt;br /&gt;
Language: Batch&lt;br /&gt;
&lt;br /&gt;
License: Open Source&lt;br /&gt;
&lt;br /&gt;
[[Category:Utilities_Third_Party]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=BR2BRS&amp;diff=3443</id>
		<title>BR2BRS</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=BR2BRS&amp;diff=3443"/>
		<updated>2013-06-19T03:08:23Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;BR2BRS&#039;&#039;&#039; is a utility to enable the windows explorer right click menu to convert a .WB or .BR file to the [[.BRS format]]. &lt;br /&gt;
&lt;br /&gt;
Language: [[Batch]]&lt;br /&gt;
&lt;br /&gt;
License: [[Open Source]]&lt;br /&gt;
&lt;br /&gt;
available BR2BRS.zip from [ftp://ftp.brulescorp.com/Brg_pub/Zip/ ftp://ftp.brulescorp.com/Brg_pub/Zip/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Utilities_Third_Party]]&lt;br /&gt;
[[Category:ftp.brulescorp.com]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=PhpIO&amp;diff=3441</id>
		<title>PhpIO</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=PhpIO&amp;diff=3441"/>
		<updated>2013-06-19T03:08:23Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The &#039;&#039;&#039;PhpIO&#039;&#039;&#039; Library requires both the ScreenIO library to function. It uses the [[BR Internet Bridge]] created by Chris Shields to run the screens you designed using the [[ScreenIO Library]] on a web server. The PhpIO library puts your ScreenIO programs on the web.&lt;br /&gt;
&lt;br /&gt;
== User Guide ==&lt;br /&gt;
&lt;br /&gt;
The User Guide for the PhpIO library will be published here when it is available.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Utilities_Third_Party]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Photo_Sorter&amp;diff=3439</id>
		<title>Photo Sorter</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Photo_Sorter&amp;diff=3439"/>
		<updated>2013-06-19T03:08:23Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;:Project Leader: [[User:Gabriel|Gabriel Bakker]]&lt;br /&gt;
:Language: [[Business Rules!]]&lt;br /&gt;
:License: ???&lt;br /&gt;
&lt;br /&gt;
*The installation files are contained in [ftp://dsg.ftpaccess.cc/Sage/Photo/Photosorter.zip Photosort.zip].&lt;br /&gt;
*The Instruction Manual is [ftp://dsg.ftpaccess.cc/Sage/Photo/Photosorter.pdf available here].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Installation===&lt;br /&gt;
*Extract the contents of the zip file to any folder you like.&lt;br /&gt;
*Copy in your brserial.dat file.&lt;br /&gt;
*Launch the included copy of BR [[4.17]].&lt;br /&gt;
*Type &#039;&#039;&#039;Run PhotoSrt&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Origin===&lt;br /&gt;
When I take photos with my digital camera, I tend to take hundred of pictures, expecting only a few to come out right. I usually take five or six photographs of each subject just to make sure I get the one that worked well.&lt;br /&gt;
&lt;br /&gt;
I was sorting through some pictures a few months ago. I would use Windows Picture and Fax viewer to view them, and when I knew which ones came out well and which ones didn&#039;t, I would use Windows Explorer to move them into different folders (&amp;quot;Good&amp;quot;, &amp;quot;Bad&amp;quot;). The process would take hours, and was extremely annoying, having to switch back and forth the whole time between two (or three with video) different programs. I decided there had to be a better way. That day the Photo Sorter was born.&lt;br /&gt;
&lt;br /&gt;
===Description===&lt;br /&gt;
The Photo Sorter is a free utility, written entirely in BR, to help sort pictures. You quickly run through and categorize your photo&#039;s, and then with the push of a button they are placed in the folders you marked. The interface is designed to be as fast and efficient as possible.&lt;br /&gt;
&lt;br /&gt;
The Photo Sorter saves what you have done after every keystroke, so if anything happens, power outage, program failure, or anything else, you don&#039;t have to redo any of your work. The next time you load the photo sorter it will pick up just where you left off. &lt;br /&gt;
&lt;br /&gt;
The Photo Sorter even handles Videos!&lt;br /&gt;
 &lt;br /&gt;
Please send any comments, compliments or complaints to [mailto:gabriel.bakker@gmail.com?Subject=PhotoSorter_Feedback Gabriel Bakker]!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Freeware]]&lt;br /&gt;
[[Category:Open Source]]&lt;br /&gt;
[[Category:Utilities Third Party]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=FnSnap&amp;diff=3437</id>
		<title>FnSnap</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=FnSnap&amp;diff=3437"/>
		<updated>2013-06-19T03:08:23Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;:Project Leader: [[:User:Gtisdale|George Tisdale]].&lt;br /&gt;
:Language: [[Business Rules!]]&lt;br /&gt;
:License: ???&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can find the latest copy of &#039;&#039;&#039;fnSnap.dll&#039;&#039;&#039; in fnsnap.zip available at [ftp://ftp.brulescorp.com/Brg_pub/Zip/]&lt;br /&gt;
&lt;br /&gt;
See also [[:Category:FnSnap]]&lt;br /&gt;
&lt;br /&gt;
*[[Library Functions|Library Functions]]&lt;br /&gt;
*[[fnSnap: File|File]]&lt;br /&gt;
:*File Management&lt;br /&gt;
::*FNBLDSORT - build a sort control file and execute the sort&lt;br /&gt;
::*FNFIL - create a file number that will increment by 1 each time a batch is created&lt;br /&gt;
::*FNFILENAME$*80 - Provide a file name&lt;br /&gt;
::*FNFILEOK - Check version number&lt;br /&gt;
::*FNFILESIZE - count number of records in a file&lt;br /&gt;
::*FNGETFILE$ - Return the name and path of an existing file&lt;br /&gt;
::*FNGETFILENAME$*80 - Create a file name from a seed&lt;br /&gt;
::*FNINDEX - Build an Index file and check for duplicates&lt;br /&gt;
::*FNNEXTFIL$ - returns the file name of the next sequential file in a given location&lt;br /&gt;
::*FNPUTFILE$ - Return the name and path of an file to be created, replaced or appended&lt;br /&gt;
::*FNSIZE - Set or correct a file size&lt;br /&gt;
::*FNUPDATE_VERSION - Change a file version and reconfigure layout&lt;br /&gt;
:*Data management&lt;br /&gt;
::*FNSEQ - Return the next sequence for a key field&lt;br /&gt;
::*FNTYPE - Move the contents of one text file into another open file&lt;br /&gt;
:*Form statements&lt;br /&gt;
::*FNCFORM$ - Create a Condensed Compiled Form Statement&lt;br /&gt;
::*FNCF$ - Process a field specification string for use in FNCFORM$&lt;br /&gt;
*[[fnSnap: Screen Processing|Screen Processing]]&lt;br /&gt;
:*Buttons, messages and dialogs&lt;br /&gt;
::*FNBUTTON - Add button on the button bar&lt;br /&gt;
::*FNCHECK - in connection with a radio dot or check box returns a 1 if checked&lt;br /&gt;
::*FNCHECK$ - places or strips ^ from an element&lt;br /&gt;
::*FNCLRBUTTON - removes a button from the button bar&lt;br /&gt;
::*FNDIALOG$*40 - Display dialog box and return selected text&lt;br /&gt;
::*FNDLG - Display a dialog box from data in a file&lt;br /&gt;
::*FNHELP - open a tip box associated with a screen using a text file&lt;br /&gt;
::*FNHELPTIP - uses David Blankenship utility to display a help record&lt;br /&gt;
::*FNOK - Pop-up &amp;quot;OK&amp;quot; question&lt;br /&gt;
::* FNOPTIONS - creates a radio dot selection pop up&lt;br /&gt;
::* FNOPTIONS$ - creates a check box selection pop up&lt;br /&gt;
::* FNPFKEYLINE - Creates a hot field string of function key options&lt;br /&gt;
::* FNPFKEY - Prints a function key message&lt;br /&gt;
::* FNRADIOCHK$ - display a radio/checkbox with a set of options&lt;br /&gt;
::* FNRADNUM - Return the option selected in a radio dot list&lt;br /&gt;
::* FNTIMEOUT - Display timeout message&lt;br /&gt;
::* FNWINBUTTONS - print one or more buttons on a screen in a designated window&lt;br /&gt;
:*String Manipulation&lt;br /&gt;
::*FNDECRYPT$ - Decrypt FNENCRYPT$&lt;br /&gt;
::*FNENCRYPT$ - Simple encryption&lt;br /&gt;
::*FNFKEY - Converts an FKEY value greater than 1000&lt;br /&gt;
::*FNNUM$ - Convert number to string&lt;br /&gt;
::*FNPHONE$ - Convert number to (###) ###-####&lt;br /&gt;
::*FNPROPER$*60 - Convert to Proper Case&lt;br /&gt;
:*Other&lt;br /&gt;
::*FNAUTO - 1 if last field exit was automatic&lt;br /&gt;
::*FNCLKBUF - Clear keyboard buffer&lt;br /&gt;
::*FNERRTRAP - Trapped Error Processing&lt;br /&gt;
::*FNINIT - Initialize variables in FNSNAP Library&lt;br /&gt;
::*FNPRINTSCREEN - stuff the keyboard to generate a print screen&lt;br /&gt;
::*FNZERO - set to number if zero&lt;br /&gt;
:*Screen input and display&lt;br /&gt;
::*FNMOD - returns the column number of a cell in a grid&lt;br /&gt;
::*FNPARSERES - returns screen resolution and BR window size for a session&lt;br /&gt;
::*FNPROGRESS - Progress bar&lt;br /&gt;
::*FNSCREEN - 24 x 80 screen display for screen painter&lt;br /&gt;
::*FNTEXTBOX - creates a text box with word wrap&lt;br /&gt;
::*FNWINSCRN - paints a screen in a window&lt;br /&gt;
::*FNWINROWCOL - in GUI mode returns rows and columns of a window&lt;br /&gt;
::*FNWINSIZE - in GUI mode creates arrays holding all window sizes&lt;br /&gt;
&lt;br /&gt;
*[[fnSnap: Window Maintenance|Window Maintenance]]&lt;br /&gt;
:*List and Grid&lt;br /&gt;
::*FNLISTSPEC$*50 - Create a window for a list/grid box&lt;br /&gt;
:*Child windows&lt;br /&gt;
::*FNWINHEAD - Print the top bar to a window&lt;br /&gt;
::*FNWINDEV - Query FNSNAP for last window opened&lt;br /&gt;
*[[fnSnap: Printing and PCL|Printing and PCL]]&lt;br /&gt;
:*Font Management&lt;br /&gt;
::*FNFONT$*30 - Create a PCL font string&lt;br /&gt;
::*FNLOADFONT$*50 - Loads a PCL font to printer&lt;br /&gt;
:*Reprinting Reports&lt;br /&gt;
::*FNCLEANLOG - part of FNREPRINT used to remove out of date reports&lt;br /&gt;
::*FNOPEN - create a log file for saved reports&lt;br /&gt;
::*FNMENUACCESS - used in connection with FNREPRINT to determine user permission to reprint a report&lt;br /&gt;
::*FNPRINT - prints a saved report opened using FNOPEN&lt;br /&gt;
::*FNREPRINT - displays a list of available saved reports and prints selected report&lt;br /&gt;
:*PCL and NWP formatting&lt;br /&gt;
::*Bar Codes and addresses&lt;br /&gt;
:::*FNPOSTNET - prints a postal bar code from a zip code&lt;br /&gt;
:::*FNCODE3OF9&lt;br /&gt;
:::*FNCODEUPC&lt;br /&gt;
&lt;br /&gt;
::*Forms and formatting&lt;br /&gt;
::*NWP Printing&lt;br /&gt;
:::*FNPRINTNWP - positions a string and aligns it right, center or decimal on a specified position&lt;br /&gt;
:*RTF Printing&lt;br /&gt;
::*FNRTFSTART - opens a source file to produce an RTF file using RTFLIB.dll&lt;br /&gt;
::*FNRTFEND - turns a source file built with FNRTFSTART into a finished document&lt;br /&gt;
:*FNREFERENCE - Prints a page reference on bottom right corner in PCL&lt;br /&gt;
:*FNPRINT_FILE - Prints a text file on Grey bar Paper&lt;br /&gt;
:*FNPRINTERS - Creates a printed list of printers and a printers.sys file&lt;br /&gt;
&lt;br /&gt;
*[[fnSnap: Date and Time|Date and Time]]&lt;br /&gt;
:*Date formatting&lt;br /&gt;
::*FNCCYYMMDD_TO_DAYS - converts CYMD to DAYS&lt;br /&gt;
::*FNDATEFWD&lt;br /&gt;
::*FNDATEREV - converts MMDDYY to YYMMDD&lt;br /&gt;
::*FNDATE$ - Creates a formatted date from DAYS input&lt;br /&gt;
::*FNDAYS_TO_MMDDCCYY - Converts DAYS to MDCY&lt;br /&gt;
::*FNDAYS_TO_MMDDYY - Converts DAYS to MMDDYY&lt;br /&gt;
::*FNMDY2YMD - converts YYMMDD to MMDDYY with century option&lt;br /&gt;
::*FNMMDDCCYY_TO_DAYS - converts MDCY to DAYS&lt;br /&gt;
::*FNMMDDYY_TO_DAYS - Converts MDY to DAYS&lt;br /&gt;
::*FNTIMMILREG - 12 hour time from 24 hour time&lt;br /&gt;
::*FNYMD2MDY - converts MMDDYY to YYMMDD with century option&lt;br /&gt;
::*FNYYMMDD_TO_DAYS - convert YMD to DAYS&lt;br /&gt;
:*Relative and special dates&lt;br /&gt;
::*FNBUSINESSDAY - returns the next business day after or including a specified date&lt;br /&gt;
::*FNDAYOFYEAR - ordinal number of days from beginning of calendar year&lt;br /&gt;
::*FNNEXTMONTH - similar date in the following month&lt;br /&gt;
::*FNPRIOR BUSINESSDAY - returns the first business day prior to a given date including the given date&lt;br /&gt;
::*FNWEEKDAY$ - Returns the day of the week&lt;br /&gt;
::*FNWEEKOFMONTH - number of time a specified day of week has occur ed in the month specified&lt;br /&gt;
::*FNWEEKOFYEAR - number of times a specified day of week has occurred in a year up to a specified date&lt;br /&gt;
&lt;br /&gt;
*[[fnSnap: Array Functions|Array Functions]]&lt;br /&gt;
:*Sorting arrays&lt;br /&gt;
::*FNSORTARRAY - sort an array with header and footer&lt;br /&gt;
::*FNSRTARY - sort an array with header and footer based on itself&lt;br /&gt;
::*FNSRTNARY -Sort a numeric array based on another array&lt;br /&gt;
:*Array arithmetic&lt;br /&gt;
::*FNCOLSUM - sums the elements of an array for a specified column&lt;br /&gt;
::*FNROWSUM - sums the elements of an array for a specified row&lt;br /&gt;
:*Searching arrays&lt;br /&gt;
::*FNCHRMAT$ - convert a numeric array to character&lt;br /&gt;
::*FNLISTSRCH - searches a character array based on a search string&lt;br /&gt;
::*FNLISTSRCHN - searches a numeric array based on a search string&lt;br /&gt;
::*FNSELECTION - selection process using two arrays&lt;br /&gt;
::*FNSRCHCRIT$*50 - search criteria for a list box&lt;br /&gt;
:*Other&lt;br /&gt;
::*FNDELROW - removes a specified row from an array and redimensions the array&lt;br /&gt;
::*FNDELROW$ - removes a specified row from an array and redimensions the array&lt;br /&gt;
::*FNADDROW - inserts a cell in the middle of a numeric array at a specified row&lt;br /&gt;
::*FNADDROW - inserts a cell in the middle of a character array at a specified row&lt;br /&gt;
::*FNPARMAT - split an array into sub-arrays&lt;br /&gt;
&lt;br /&gt;
*[[fnSnap: Miscellaneous Functions|Miscellaneous Functions]]&lt;br /&gt;
:*Email&lt;br /&gt;
::*FNEMAIL - creates an email file for email monitor&lt;br /&gt;
::*FNEMAILFILE - inserts a text file into an email for email monitor&lt;br /&gt;
:*Formatting&lt;br /&gt;
::*FNLEADZERO$ - obsolete replace with CNVRT$(&amp;quot;PIC(###)&amp;quot;,x)&lt;br /&gt;
::*FNCHECKAMOUNT$ - returns English words for a dollar amount&lt;br /&gt;
:*Progress&lt;br /&gt;
::*FNPROG - displays a progress bar for a process&lt;br /&gt;
::*FNPROGRESS - displays a progress bar for a process&lt;br /&gt;
:*Other&lt;br /&gt;
::*FNCLKBUF - clears the keyboard buffer of extra key strokes&lt;br /&gt;
::*FNCURDRV$ - returns the current drive and directory&lt;br /&gt;
::*FNMSEXE$ - return the installed location of a Microsoft compliant program installation&lt;br /&gt;
::*FNX$ - returns X if true BLANK if false&lt;br /&gt;
&lt;br /&gt;
*[[fnSnap: FNSNAP Obsolete functions|Obsolete functions]]&lt;br /&gt;
:*Window and screen processing&lt;br /&gt;
::*FNMGCLR - clears a message form the fnpick message line&lt;br /&gt;
::*FNSAVPART - legacy function to save a portion of the screen - obsolete in 4.17&lt;br /&gt;
::*FNRELPART - legacy function to clear a portion of the screen obsolete in 4.17&lt;br /&gt;
::*FNWIN - legacy function to open a window in numeric order&lt;br /&gt;
::*FNCLSWIN - legacy function to close a window opened by FNWIN&lt;br /&gt;
::*FNPM - legacy message box on the main window&lt;br /&gt;
:*Point and pick&lt;br /&gt;
::*FNKEYSEL - direct file look up function requires a fixed position font&lt;br /&gt;
::*FNPICK_EX - A point and shoot legacy using a single matrix requires a fixed position font&lt;br /&gt;
::*FNPICK - A point and shoot legacy using a single matrix requires a fixed position font&lt;br /&gt;
::*FNKEYSEL_EX - a legacy direct file access point and shoot requires a fixed sized font&lt;br /&gt;
::*FNPOPUP - legacy code for a pop-up choice box&lt;br /&gt;
:*Supporting functions&lt;br /&gt;
::*Data transfer between program and library&lt;br /&gt;
::*FNWINDEV - returns the number of the currentlyactive FNSNAP window using the old system&lt;br /&gt;
::*FNLEADZERO$&lt;br /&gt;
::*FNGETK$ - \fs20&lt;br /&gt;
::*FNSETALL - set all elements of an array&lt;br /&gt;
::*FNSETSEL - set all elements of an array&lt;br /&gt;
::*FNPRTPICKBAR - a function to position a colored pick bar in FNPICK&lt;br /&gt;
::*FNZLPAD$ - pads a number with zeros and converts to string&lt;br /&gt;
::*FNINIT - initializes the variable required by the original FNSNAP functions&lt;br /&gt;
::*FNNOKEY - chekc to see if CMDKEY or FKEY were pressed&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
FnSnap is also discussed in [[Library Facility]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:FnSnap]]&lt;br /&gt;
[[Category:Utilities]]&lt;br /&gt;
[[Category:Utilities Third Party]]&lt;br /&gt;
[[Category:ftp.ads.net]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=CURL&amp;diff=3435</id>
		<title>CURL</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=CURL&amp;diff=3435"/>
		<updated>2013-06-19T03:08:23Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Messagebox|Please note that  [[Business Rules!]] [[4.20]] provides native [[HTTP]] support.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;cURL&#039;&#039;&#039; is a command line tool for transferring files with URL syntax, supporting FTP, FTPS, [[HTTP]], HTTPS, SCP, SFTP, TFTP, TELNET, DICT, LDAP, LDAPS and FILE. cURL supports SSL certificates, HTTP POST, HTTP PUT, FTP uploading, HTTP form based upload, proxies, cookies, user+password authentication (Basic, Digest, NTLM, Negotiate, kerberos...), file transfer resume, proxy tunneling and a busload of other useful tricks.&lt;br /&gt;
&lt;br /&gt;
Curl is free and open software that compiles and runs under a wide variety of operating systems. Curl exists thanks to efforts from many contributors. &lt;br /&gt;
See [http://curl.haxx.se/ cURL Home Page]&lt;br /&gt;
&lt;br /&gt;
See also: [[Wikipedia:Web scraping]]&lt;br /&gt;
&lt;br /&gt;
The basic idea is you call cURL using a system call and you give it a URL and a file name to save the page under. Curl goes to the URL you enter, just as if you entered it in Internet explorer, and it saves the resulting page as an html file.&lt;br /&gt;
&lt;br /&gt;
In this example we wanted to write a function to perform a reverse phone number look-up. I can&#039;t send you the whole source code because it is proprietary, but I don&#039;t think a little excerpt will hurt. We call Curl and we give it a URL at whitepages.com. We figured out that if you go to the URL:  [http://www.whitepages.com/15055/search/ReversePhone?phone=8172745220]  it will display an html page showing who the phone number 817 274 5220 &lt;br /&gt;
belongs to (which happens to be Nizza Pizza).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  00100 REV_LOOK: ! Reverse Lookup By Phone Number&lt;br /&gt;
  00120    def library Fnrev_Look(Number$,Mat Result$)&lt;br /&gt;
  00140       let Fnrev_Look=1 ! Assume Success !:&lt;br /&gt;
           mat Web_Page$(0)&lt;br /&gt;
  00150       if Exists(&amp;quot;address.html&amp;quot;) then execute &amp;quot;*free address.html&amp;quot;&lt;br /&gt;
  00160       execute &#039;sy -M curl http://www.whitepages.com/15055/search/ReversePhone?phone=&#039; &amp;amp; Number$ &amp;amp; &#039; -A &amp;quot;Mozilla/4.0&amp;quot; -o address.html -s&#039;&lt;br /&gt;
  00200       if Fnread_Page(&amp;quot;address.html&amp;quot;,Mat Web_Page$) then&lt;br /&gt;
  00270          let Response_Type=Fnget_Type(Mat Web_Page$)&lt;br /&gt;
  00272          if Response_Type then ! If Respose Type Found !:&lt;br /&gt;
                 let Fnrev_Look=Fnparse_Page(Response_Type, Mat Web_Page$, Mat Result$) ! Parse It !:&lt;br /&gt;
                 else !:&lt;br /&gt;
                 let Fnrev_Look=0 ! Failed To Get Parse Response Type&lt;br /&gt;
  00280       else&lt;br /&gt;
  00285          let Fnrev_Look=0 ! Failed To Read Page, Check Internet&lt;br /&gt;
  00290       end if&lt;br /&gt;
  00340 _END_REV_LOOK: fnend&lt;br /&gt;
&lt;br /&gt;
This function takes the phone number to look up, and it builds the URL and passes it to curl in line 160. Line 160 tells Curl to preform the look-up and save the resulting page as address.html in the current directory.&lt;br /&gt;
&lt;br /&gt;
After that, on line 200, we call a function that reads the results into a matrix. After that we call various functions to parse through the matrix looking for the Address information.&lt;br /&gt;
&lt;br /&gt;
During our investigation of the web site we discovered that whitepages.com returns several different web pages depending on if there are 0 result(s), 1 result(s) or many result(s) found. Our parser functions look at the format of the address.html file that curl saved, to determine which type it is. Then, based on that information, it parses the results and builds an address array called Mat Result$ that it returns to the caller.&lt;br /&gt;
&lt;br /&gt;
If you call this function using 817 274 5220, you end up with a mat results$ similar to:&lt;br /&gt;
&lt;br /&gt;
*Results$(1)=&amp;quot;Nizza Pizza &amp;amp; Pasta&amp;quot;&lt;br /&gt;
*Results$(2)=&amp;quot;1430 S Cooper St&amp;quot;&lt;br /&gt;
*Results$(3)=&amp;quot;Arlington&amp;quot;&lt;br /&gt;
*Results$(4)=&amp;quot;TX&amp;quot;&lt;br /&gt;
*Results$(5)=&amp;quot;76013&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Needs Help]]&lt;br /&gt;
[[Category:Utilities Third Party]]&lt;br /&gt;
[[Category:Open Source]]&lt;br /&gt;
[[Category:Freeware]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=GotoMeeting&amp;diff=3433</id>
		<title>GotoMeeting</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=GotoMeeting&amp;diff=3433"/>
		<updated>2013-06-19T03:08:23Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;br /&gt;
*[http://www.gotoassist.com/ goto assist.com]&lt;br /&gt;
*[https://www2.gotomeeting.com/en_US/entry/entry.tmpl goto meeting.com]&lt;br /&gt;
&lt;br /&gt;
[[Category:Utilities Third Party]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=MyEdit_(BR_Edition)&amp;diff=3431</id>
		<title>MyEdit (BR Edition)</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=MyEdit_(BR_Edition)&amp;diff=3431"/>
		<updated>2013-06-19T03:08:23Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;MyEdit - BR Edition&#039;&#039;&#039; (&#039;&#039;&#039;MyEditBR&#039;&#039;&#039;) is the first third-party [[editor]] to be specifically written to support the [[Business Rules!]] language.&lt;br /&gt;
&lt;br /&gt;
It is the most popular editor for Business Rules! [[4.18]]+ editing&lt;br /&gt;
&lt;br /&gt;
With it&#039;s high level of integration with BR! and the built-in capabilities MyEditBR will become a valued tool for all BR! developers.  MyEditBR is based on SynEdit[http://synedit.sourceforge.net/].&lt;br /&gt;
&lt;br /&gt;
==Extrenal Link(s)==&lt;br /&gt;
*[http://www.mills-enterprise.ca/ Mills Enterprise Website]&lt;br /&gt;
*[http://support.mills-enterprise.ca/ Mills Enterprise - Support Forums]&lt;br /&gt;
&lt;br /&gt;
==Support==&lt;br /&gt;
MyEditBR is the product of [[Mills Enterprise]] with the support of [[Western Canadian Software]].  &lt;br /&gt;
&lt;br /&gt;
The support is handled by [[Ryan J. Mills]] and he can typically be reached on the BR Forums, the Mills Enterprise Website or via his private email address.&lt;br /&gt;
&lt;br /&gt;
There are two versions of MyEditBR: &#039;&#039;&#039;Free&#039;&#039;&#039; and &#039;&#039;&#039;Supported&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
While MyEditBR is free to download and use, the free version has certain features and capabilities turned off.  You will still be able to use MyEditBR for your average day to day BR! programming responsibilities.&lt;br /&gt;
&lt;br /&gt;
The supported version of MyEditBR gives the user a license to more advanced features found in the program.&lt;br /&gt;
&lt;br /&gt;
Please note that there is only one program.  The supported features are turned on with a valid support license.  It is easier to describe the differences as if they were from two separate programs.&lt;br /&gt;
&lt;br /&gt;
Here is a list of current features showing the differences between the two versions:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Number of open files&#039;&#039;&#039;&amp;lt;br&amp;gt;- Free version is limited to 5 open files at any one time.&amp;lt;br&amp;gt;- Supported version is unlimited.&lt;br /&gt;
* &#039;&#039;&#039;Color and Language Support&#039;&#039;&#039;&amp;lt;br&amp;gt;- Free version doesn&#039;t support importing/exporting color and language customizations from within the editor.&amp;lt;br&amp;gt;- Supported version has built-in importing/exporting capabilities.&lt;br /&gt;
* &#039;&#039;&#039;Automated Bug Reporting&#039;&#039;&#039;&amp;lt;br&amp;gt;- Free version doesn&#039;t provide this.&amp;lt;br&amp;gt;- Supported version will offer to submit bug report directly to Mills Enterprise via the web.&lt;br /&gt;
* &#039;&#039;&#039;Advanced Editor Options&#039;&#039;&#039;&amp;lt;br&amp;gt;- Free version doesn&#039;t provide this.&amp;lt;br&amp;gt;- Supported version can show modified line statuses and supports editing in either editor while in Split View mode.&lt;br /&gt;
* &#039;&#039;&#039;BR Support&#039;&#039;&#039;&amp;lt;br&amp;gt;- Free version doesn&#039;t provide this.&amp;lt;br&amp;gt;- Supported version integrates directly with BR to provide direct editing of .WB/.BR files and compiling back to .BR/.WB files.  As well as providing on the fly native BR syntax checking while editing (appears as additional HWEs)&lt;br /&gt;
* &#039;&#039;&#039;Advanced Debugging Features&#039;&#039;&#039;&amp;lt;br&amp;gt;- Free version has the standard debugger support&amp;lt;br&amp;gt;- Supported version provides advanced capabilities like Conditional Breakpoints.&lt;br /&gt;
* &#039;&#039;&#039;Program Support&#039;&#039;&#039;&amp;lt;br&amp;gt;- Free version doesn&#039;t provide this.&amp;lt;br&amp;gt;- Supported version provides additional features such as Checking for Updates.&lt;br /&gt;
&lt;br /&gt;
This list is not complete and will be updated as completed features get added to the program.&lt;br /&gt;
&lt;br /&gt;
The licensing terms have not been finalized to date as such all copies of MyEditBR available from the ADS FTP site and directly from Mills Enterprise (Ryan Mills) have a temporary license provided that will expire after a given date.&lt;br /&gt;
&lt;br /&gt;
To see the details of the currently installed license, open the Help|About program menu item.  (Doing so on a Remote Desktop Connection is very very slow and may take a long time for the about dialog to fade away)&lt;br /&gt;
&lt;br /&gt;
==Installation==&lt;br /&gt;
*To move the keyboard shortcut assignments from one installation to another copy the [Program Installation Directory]\MyEditBR.actbindings file.&lt;br /&gt;
&lt;br /&gt;
*To move your color setup for any or all languages use the Help&amp;gt;Export and Help&amp;gt;Import options.&lt;br /&gt;
&lt;br /&gt;
*To implement the BR Wiki as context sensitive help, see the [[Lookup project]].&lt;br /&gt;
&lt;br /&gt;
==Portable Installation==&lt;br /&gt;
&lt;br /&gt;
/forceportable is the command line option needed to make MyEditBR behave properly on a USB install.&lt;br /&gt;
&lt;br /&gt;
You need the following setup (Manually configured):&lt;br /&gt;
&lt;br /&gt;
# Make a folder on your USB key.&lt;br /&gt;
# Copy all files and folders where you have MyEditBR installed on your main machine to the folder created in Step 1. (This will typically be &amp;quot;c:\program files\mills enterprise\myeditbr&amp;quot;.)&lt;br /&gt;
# Copy all files and folders from your MyEditBR data directory into the folder created in Step 1. (This data folder will be found in one of two different places depending on the operating system you have. WinXP: &amp;quot;c:\documents and settings\(your username)\Application Data\Mills Enterprise\MyEditBR&amp;quot;) (Please replace (your username) with the appropriate value. Smile)&lt;br /&gt;
&lt;br /&gt;
You need to edit your brconfig.sys file and add the command line option /forceportable) it to the EDITOR option there as well as point it to your new USB install of MyEditBR.&lt;br /&gt;
&lt;br /&gt;
Once that is done, you should be good to go.&lt;br /&gt;
&lt;br /&gt;
==Features==&lt;br /&gt;
* &#039;&#039;&#039;Hints Warnings and Errors (HWE)&#039;&#039;&#039;&lt;br /&gt;
**Built in checking for the most commonly encountered problems when moving from the standard BR editor to MyEditBR.&lt;br /&gt;
* &#039;&#039;&#039;Syntax Highlighting&#039;&#039;&#039;&lt;br /&gt;
**Color coded syntax highlighting provides easy visual ques to program code.&lt;br /&gt;
* &#039;&#039;&#039;Code Completion&#039;&#039;&#039;&lt;br /&gt;
**Providing quick shortcuts to long function names as well as showing the parameters of current function&lt;br /&gt;
* &#039;&#039;&#039;Refactoring&#039;&#039;&#039;&lt;br /&gt;
**The latest versions of the application support [[refactoring]] of [[variables]], [[labels]] and [[named forms]].&lt;br /&gt;
* &#039;&#039;&#039;Line Renumbering&#039;&#039;&#039;&lt;br /&gt;
**As powerful as BR but with additional capabilities.&lt;br /&gt;
* &#039;&#039;&#039;BR Debugger&#039;&#039;&#039; (requires BR! [[4.18]]+)&lt;br /&gt;
**Visual Debugger, Watches, Breakpoints, Conditional Breakpoints (Supported version only), Hover over tool tip variable evaluation and more.&lt;br /&gt;
* &#039;&#039;&#039;Re-mappable Keyboard Shortcuts&#039;&#039;&#039;&lt;br /&gt;
**Don&#039;t like a given keyboard short cut, then change it!&lt;br /&gt;
* &#039;&#039;&#039;Highly Customizable&#039;&#039;&#039;&lt;br /&gt;
**Persistent configuration changes between runs of the application.  Includes window and tool window size and position storage and configuration persistence.&lt;br /&gt;
* &#039;&#039;&#039;Full Multi-Monitor Support&#039;&#039;&#039;&lt;br /&gt;
**If you work on a laptop with an additional monitor at work but not at home, MyEditBR will always start up on the correct monitor.&lt;br /&gt;
* &#039;&#039;&#039;Live Development&#039;&#039;&#039;&lt;br /&gt;
**New features can be added/considered on request&lt;br /&gt;
* &#039;&#039;&#039;Alt+Mouse Scrolling Changes Font Size&#039;&#039;&#039;&lt;br /&gt;
**This is also implemented as keyboard shortcuts (Ctrl+Shift+&amp;lt; and Ctrl+Shift+&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
==Settings Files==&lt;br /&gt;
To copy settings between multiple installations you may need to copy one or more of the following files.&lt;br /&gt;
&lt;br /&gt;
*MyEditBR.actbindings - Primarily Menu / Tool bar shortcuts (action bindings)&lt;br /&gt;
*MyEditBR.ardetails - Auto-Recovery details in case of a crash during editing&lt;br /&gt;
*MyEditBR.broptions - BR specific options (HWE for example)&lt;br /&gt;
*MyEditBR.desktop - Screen docking layout (Includes dockable tool windows)&lt;br /&gt;
*MyEditBR.exclusions - BR HWE Global Exclusions&lt;br /&gt;
*MyEditBR.fileextensions - Additional file extension handling (.cfg -&amp;gt; text file)&lt;br /&gt;
*MyEditBR.filesmru - MRU file list&lt;br /&gt;
*MyEditBR.genops - Editor General options (spell checker, AutoNewFileType, etc)&lt;br /&gt;
*MyEditBR.highlighters - Additional custom highlighters (??)&lt;br /&gt;
*MyEditBR.options - SynEdit specific options&lt;br /&gt;
*MyEditBR.pagesetup - SynEdit print page setup options (??)&lt;br /&gt;
*MyEditBR.searchhistory - Search/Replace history&lt;br /&gt;
*MyEditBR.sessionmru - MRU session file list&lt;br /&gt;
*MyEditBR.usertools - User Tools&lt;br /&gt;
*MyEditBR.visparm - Editor Visual parameters (Editor State and Position, Tool bar states, positions and customizations)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==See Also==&lt;br /&gt;
*Errors [[1154]] and [[1156]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Utilities Third Party]]&lt;br /&gt;
[[Category:Supports Regular Expression]]&lt;br /&gt;
[[Category:Purchasable]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=Category:Install_Builder&amp;diff=3429</id>
		<title>Category:Install Builder</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=Category:Install_Builder&amp;diff=3429"/>
		<updated>2013-06-19T03:08:23Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Pages in this category discuss software that can be used to build installers.&lt;br /&gt;
&lt;br /&gt;
[[Category: Utilities Third Party]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=AutoIt&amp;diff=3427</id>
		<title>AutoIt</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=AutoIt&amp;diff=3427"/>
		<updated>2013-06-19T03:08:23Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[image:autoit_scripter_blue_userbar.png|center]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;AutoIt&#039;&#039;&#039; is a &#039;growing&#039; [[scripting language]].  It started as an add-on tool to automate basic tasks in GUI&#039;s of other programs.&lt;br /&gt;
These tasks (like sending a keystroke or clicking a button) are still the core components of an AutoIt script. However with the recent [[GUI]] additions, you can now incorporate your own graphical interface using native AutoIt script commands.&lt;br /&gt;
The new COM (Object) functionality fills the gap with WSH[http://en.wikipedia.org/wiki/Windows_Scripting_Host] languages, such as VBScript/JScript. Under certain conditions you can now even use WSH-like scripts on otherwise unsupported operating systems (like Windows 9x/Me/NT).&lt;br /&gt;
&lt;br /&gt;
With this combination of GUI Automation, GUI Interfaces and COM support, AutoIt offers you a powerful scripting tool that is able to compete with fully-fledged scripting languages like WSH or KiXStart[http://www.kixtart.org/]).&lt;br /&gt;
&lt;br /&gt;
AutoIt has been designed to work on Windows 95, 98, ME, NT 4, 2000, XP, 2003 and Windows Vista. With no annoying runtime libraries required!&lt;br /&gt;
&lt;br /&gt;
*[http://www.autoitscript.com/ Official Web Site]&lt;br /&gt;
*[http://www.autoitscript.com/autoit3/docs/ Documentation]&lt;br /&gt;
*[http://www.autoitscript.com/wiki/Main_Page AutoIt Wiki]&lt;br /&gt;
[[Category:Utilities Third Party]]&lt;br /&gt;
[[Category:Freeware]]&lt;br /&gt;
[[Category: Install Builder]]&lt;br /&gt;
[[Category:Programming Language]]&lt;br /&gt;
[[Category:Scripting Language]]&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
	<entry>
		<id>https://brwiki2.brulescorp.com/brwiki2/index.php?title=EditPad_Pro&amp;diff=3425</id>
		<title>EditPad Pro</title>
		<link rel="alternate" type="text/html" href="https://brwiki2.brulescorp.com/brwiki2/index.php?title=EditPad_Pro&amp;diff=3425"/>
		<updated>2013-06-19T03:08:23Z</updated>

		<summary type="html">&lt;p&gt;Admin: 1 revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;EditPad Pro&#039;&#039;&#039; is a powerful and versatile text editor or word processor. &lt;br /&gt;
&lt;br /&gt;
==External Links==&lt;br /&gt;
&lt;br /&gt;
*[http://www.editpadpro.com/ EditPad Pro Official Home]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;noinclude&amp;gt;&lt;br /&gt;
[[Category:Utilities Third Party]]&lt;br /&gt;
[[Category:Supports Regular Expression]]&lt;br /&gt;
[[Category:Purchasable]]&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Admin</name></author>
	</entry>
</feed>