

<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.amigaos.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=James+Jacobs</id>
	<title>AmigaOS Documentation Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.amigaos.net/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=James+Jacobs"/>
	<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/wiki/Special:Contributions/James_Jacobs"/>
	<updated>2026-05-07T14:13:38Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.0</generator>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=AmigaGuide_101&amp;diff=12570</id>
		<title>AmigaGuide 101</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=AmigaGuide_101&amp;diff=12570"/>
		<updated>2025-02-12T10:04:54Z</updated>

		<summary type="html">&lt;p&gt;James Jacobs: Fixed SYSTEM action command example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;adapted from the original AmigaMail article by Jerry Hartzler&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Compared to other platforms, Amiga-based utilities that display on-line documentation are relatively weak.  Until 1991, Amiga users had to rely on basic text viewing utilities like More, which lack the navigational capabilities of hypertext programs.  In a hypertext environment, when the user wants more information on a subject, the user simply clicks on a word and the hypertext utility automatically cross references the subject.  No type of hypertext-like utility was available on the Amiga--that is, until AmigaGuide came along.&lt;br /&gt;
&lt;br /&gt;
[[AmigaGuide]] can display plain ASCII text files and AmigaGuide databases.  An AmigaGuide database is a single file that consists of a set of documents called nodes.  If you were to convert a book into an AmigaGuide database, a convenient way to organize the database is to make each chapter of the book into a node.  Each node may contain references to other nodes (chapters) or databases (other books), using a link.  When a user selects a link--which usually appears in the form of a button within the text--AmigaGuide dereferences the link and displays its node.  This makes it easier for the user to find the information he is looking for because the user no longer needs to search through a document.  AmigaGuide already knows where the information is.&lt;br /&gt;
&lt;br /&gt;
Buttons within AmigaGuide can do other actions as well, such as execute Shell or ARexx commands.  An ARexx port is also built into AmigaGuide providing users the means to support and control the utility.  Therefore, like a book, an AmigaGuide database can display illustrations.  It can go a step beyond by playing sounds and music, and by being truly interactive with the user, able to ask questions and evaluate responses.&lt;br /&gt;
&lt;br /&gt;
This article was written to familiarize you with AmigaGuide and the format of its databases.&lt;br /&gt;
&lt;br /&gt;
== Setting up AmigaGuide ==&lt;br /&gt;
&lt;br /&gt;
AmigaGuide consists of the AmigaGuide utility and an Exec library called amigaguide.library.  AmigaGuide should be placed in the SYS:Utilities drawer and amigaguide.library placed in the Libs: drawer.  As of Release 3, the OS comes with a utility called MultiView that understands and displays AmigaGuide databases. MultiView requires amigaguide.datatype and datatypes.library in order to display AmigaGuide databases.&lt;br /&gt;
&lt;br /&gt;
AmigaGuide can run from the Workbench or the Shell.  To run from Workbench, the default tool of an AmigaGuide database or text icon should be set to &#039;&#039;&#039;AmigaGuide&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
From the Shell, use the following command template:&lt;br /&gt;
&lt;br /&gt;
    AmigaGuide &amp;lt;my_DataBase&amp;gt;&lt;br /&gt;
&lt;br /&gt;
where &amp;lt;my_DataBase&amp;gt; is the name of the AmigaGuide database or text file to display.&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
    1&amp;gt; AmigaGuide Autodocs&lt;br /&gt;
&lt;br /&gt;
attempts to open the Autodocs database.  In its search for a database, AmigaGuide will first look in the current directory and then through the AmigaGuide path for the database.&lt;br /&gt;
&lt;br /&gt;
The AmigaGuide path is a global environment variable.  AmigaGuide stores its environment variables in the ENV:AmigaGuide directory assigned in RAM:.&lt;br /&gt;
&lt;br /&gt;
The variable named path contains the list of directory names that AmigaGuide will search through when it attempts to open a database. Directory names are separated by a space.  The path variable is set and stored in the ENV:AmigaGuide directory through the use of the AmigaDOS SetEnv command (Note that as of Release 3, if the AmigaGuide directory does not exist, SetEnv will not create it).&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
    1&amp;gt; SetEnv AmigaGuide/Path &amp;quot;Workbench:Autodocs Workbench:Includes&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Of course all variables set in RAM: disappear once the computer is turned off.  To prevent this, copy the file ENV:AmigaGuide/Path to the ENVARC:AmigaGuide directory.  The system copies the ENVARC: directory to ENV: upon start-up.&lt;br /&gt;
&lt;br /&gt;
The MultiView utility uses the  amigaguide.datatype which uses this the environment variable as its path.&lt;br /&gt;
&lt;br /&gt;
== The AmigaGuide Window ==&lt;br /&gt;
&lt;br /&gt;
AmigaGuide displays text within an Intuition window.  The window contains scroll bars, buttons and pull-down menus making it easy to browse, search and print text.&lt;br /&gt;
&lt;br /&gt;
[[File:Amigaguide.png]]&lt;br /&gt;
&lt;br /&gt;
Along the top edge of the AmigaGuide window is a row of six navigation buttons:&lt;br /&gt;
&lt;br /&gt;
* Contents: This button displays the Table Of Contents for the current database or node.  See the @NODE and @TOC commands below.&lt;br /&gt;
&lt;br /&gt;
* Index: This button displays the Index for the current database.  See the @INDEX command below.&lt;br /&gt;
&lt;br /&gt;
* Help: By default, this button displays the database named help.guide in the s: directory.  Under 3.0, the database is named amigaguide.guide in the Help:&amp;lt;country&amp;gt;/sys directory.  This database contains help in using AmigaGuide.&lt;br /&gt;
&lt;br /&gt;
* Retrace: This button goes back to the previous node.&lt;br /&gt;
&lt;br /&gt;
* Browse: These buttons step through the nodes in sequential order (the order they appear in the database).&lt;br /&gt;
&lt;br /&gt;
== AmigaGuide Databases ==&lt;br /&gt;
&lt;br /&gt;
Creating an AmigaGuide database is quite simple.  An AmigaGuide database is basically an ASCII text file, embedded with commands to tell AmigaGuide what to do.  Let&#039;s take a look at the commands used in AmigaGuide and then make up a simple database.&lt;br /&gt;
&lt;br /&gt;
There are three types of AmigaGuide commands.  Database commands break up a document into nodes.  Node commands set attributes within a node.  Action commands are only found within a special node command called a &#039;&#039;&#039;link point&#039;&#039;&#039;.  As the name implies, action commands perform some action.&lt;br /&gt;
&lt;br /&gt;
=== Database Commands ===&lt;br /&gt;
&lt;br /&gt;
Database commands should not be used within the nodes themselves. They must start in the first column of a line.  If a line in an AmigaGuide database begins with an at (@) sign, then AmigaGuide interprets the line as a command.  Although the AmigaGuide commands appear here in upper-case, AmigaGuide commands are not case sensitive.&lt;br /&gt;
&lt;br /&gt;
* @DATABASE &amp;lt;name&amp;gt; - This command identifies a file as an AmigaGuide database.  It must be the first line of the database.&lt;br /&gt;
&lt;br /&gt;
* @NODE &amp;lt;name&amp;gt; &amp;lt;title&amp;gt; - This command indicates the start of a node. The first node of a database should be named MAIN.  MAIN is typically the master table of contents for the database (see the @TOC node command in the next section).  When AmigaGuide displays the node, it displays &amp;lt;title&amp;gt; in the window&#039;s title bar.  If there are any spaces in the &amp;lt;title&amp;gt;, it must be in quotes.  A node name cannot contain spaces, tabs, colons (&#039;:&#039;) or slants (&#039;/&#039;).&lt;br /&gt;
&lt;br /&gt;
* @DNODE &amp;lt;name&amp;gt; - This command indicates the start of a dynamic node. Dynamic nodes are beyond the scope of this introductory article and therefore are not discussed here.&lt;br /&gt;
&lt;br /&gt;
* @INDEX &amp;lt;node name&amp;gt; - This command tells AmigaGuide which node to use as the index for the database.  When the user hits the &#039;&#039;&#039;Index&#039;&#039;&#039; button at the top of the AmigaGuide window, AmigaGuide will display the node specified by this command.  The node can be in another database.  If the node is in another database, the node name is the file name of the database followed by a slant (`/`), followed by the name of the node in the other database.  For example, to access the MAIN node in another database called other_database, the link point looks like this:&lt;br /&gt;
&lt;br /&gt;
    @{&amp;quot;my label&amp;quot; LINK other_database/MAIN}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;The name of the other database can contain a full path to the other database.  If it doesn&#039;t, AmigaGuide will search the AmigaGuide path for the other database.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* @REMARK &amp;lt;remark&amp;gt; - This commands lets you add programmer remarks to a database.  AmigaGuide ignores the remarks.&lt;br /&gt;
&lt;br /&gt;
=== Node Commands ===&lt;br /&gt;
&lt;br /&gt;
These commands are only valid within a @NODE.  They must start in the&lt;br /&gt;
first column of a line unless otherwise noted.&lt;br /&gt;
&lt;br /&gt;
* @ENDNODE &amp;lt;name&amp;gt; - This command ends a node.&lt;br /&gt;
&lt;br /&gt;
* @TITLE &amp;lt;title&amp;gt; - AmigaGuide displays &amp;lt;title&amp;gt; in the node&#039;s window title bar.  It must start at the beginning of a line.  This command isn&#039;t necessary if you use the &amp;lt;title&amp;gt; option in @NODE.&lt;br /&gt;
&lt;br /&gt;
* @TOC &amp;lt;node name&amp;gt; - This command tells AmigaGuide which node to display when the user hits the Contents button while displaying this node.  If a node does not have a @TOC command, the table of contents defaults to MAIN.  The &amp;lt;node name&amp;gt; can be in another database.  See the @INDEX command in the [[#Database Commands|Database Commands]] section for more information on the format of &amp;lt;node name&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* @PREV &amp;lt;node name&amp;gt; - The Browse buttons can be reprogrammed so as not to step through the nodes in sequential order.  For example, if this command appears in a @NODE, AmigaGuide  will display the &amp;lt;node name&amp;gt; node when the user selects the &#039;&#039;&#039;&amp;lt; Browse&#039;&#039;&#039; button while in the current node.  The &amp;lt;node name&amp;gt; can be in another database.  See the @INDEX command in the [[#Database Commands|Database Commands]] section for more information on the format of &amp;lt;node name&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* @NEXT &amp;lt;node name&amp;gt; - Similar to @PREV but will display the &amp;lt;node name&amp;gt; node when the user selects &#039;&#039;&#039;Browse &amp;gt;&#039;&#039;&#039; button while in the current node.  The &amp;lt;node name&amp;gt; can be in another database.  See the @INDEX command in the [[#Database Commands|Database Commands]] section for more information on the format of &amp;lt;node name&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* @{&amp;quot;&amp;lt;label&amp;gt;&amp;quot; &amp;lt;action command&amp;gt;} - This command is referred to as a link point.  AmigaGuide makes the string &amp;lt;label&amp;gt; into a button.  The &amp;lt;label&amp;gt; must be enclosed by quotes.  When the user hits that button, AmigaGuide carries out &amp;lt;action command&amp;gt; (see the next section of this article for a description of action commands).  A link point does not have to start in the first column, it can appear anywhere on a line.&lt;br /&gt;
&lt;br /&gt;
=== Action Commands ===&lt;br /&gt;
&lt;br /&gt;
These commands are for use with the link point command described in the [[#Node Commands|Node Commands]] section of this article.&lt;br /&gt;
&lt;br /&gt;
* LINK &amp;lt;node name&amp;gt; &amp;lt;line#&amp;gt; - This command loads and displays the &amp;lt;node name&amp;gt; node at the line number specified in &amp;lt;line #&amp;gt;.  The &amp;lt;line #&amp;gt; parameter is optional and it defaults to zero.  The node can be in another database.  The &amp;lt;node name&amp;gt; can be in another database.  See the @INDEX command in the [[#Database Commands|Database Commands]] section for more information on the format of &amp;lt;node name&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;The &amp;lt;line #&amp;gt; parameter is optional and it defaults to zero.  The default line number is line zero.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* RX &amp;lt;ARexx command&amp;gt; - This commands executes the ARexx macro named in &amp;lt;ARexx command&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* RXS &amp;lt;command&amp;gt; - This commands executes the ARexx string file named in &amp;lt;command&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* SYSTEM &amp;lt;command&amp;gt; - This commands executes the AmigaDOS command named in &amp;lt;command&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
* QUIT - When AmigaGuide encounters this command is shuts down the current database.&lt;br /&gt;
&lt;br /&gt;
== A Working Database ==&lt;br /&gt;
&lt;br /&gt;
As an example, Let&#039;s make the text file below into a simple AmigaGuide database.  The simple database will consists of a single node.&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;nowiki&amp;gt; What is a user interface? This sweeping phrase covers all&lt;br /&gt;
  aspects of communication between the user and the computer. It&lt;br /&gt;
  includes the innermost mechanisms of the computer and rises to&lt;br /&gt;
  the height of defining a philosophy to guide the interaction&lt;br /&gt;
  between human and machine.  Intuition is, above all else, a&lt;br /&gt;
  philosophy turned into software.  See the Amiga ROM Kernel&lt;br /&gt;
  Reference Manual: Libraries for more information.&lt;br /&gt;
&lt;br /&gt;
  Intuition screens are the basis of any display Intuition can&lt;br /&gt;
  make. Screens determine the fundamental characteristics of the&lt;br /&gt;
  display such as the resolution and palette and they set up the&lt;br /&gt;
  environment for multiple, overlapping windows that makes it&lt;br /&gt;
  possible for each application to have its own separate visual&lt;br /&gt;
  context.&lt;br /&gt;
&lt;br /&gt;
  Windows are rectangular display areas that open on screens.&lt;br /&gt;
  The window acts as a virtual terminal allowing a program to&lt;br /&gt;
  interact with the user as if it had the entire display all to&lt;br /&gt;
  itself. Windows are moveable and can be positioned anywhere&lt;br /&gt;
  within the screen on which they exist.  Windows may also have a&lt;br /&gt;
  title and borders containing various gadgets for controlling&lt;br /&gt;
  the window.&lt;br /&gt;
&lt;br /&gt;
  Gadgets are software controls symbolized by an image that the&lt;br /&gt;
  user can operate with the mouse or keyboard.  They are the&lt;br /&gt;
  Amiga&#039;s equivalent of buttons, knobs and dials.&lt;br /&gt;
&lt;br /&gt;
  Menus are command and option lists associated with an&lt;br /&gt;
  application window that the user can bring into view at any&lt;br /&gt;
  time.  These lists provide the user with a simple way to access&lt;br /&gt;
  features of the application without having to remember or enter&lt;br /&gt;
  complex character-based command strings.&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If AmigaGuide displayed the file above, it would appear without any buttons linking it to text files or databases.  To mark this file as an AmigaGuide database, add the @DATABASE command.  As mentioned earlier, it must start on the first line in the first column of the file.&lt;br /&gt;
&lt;br /&gt;
Since there will be no index for this database, the next command can be a @NODE.  For AmigaGuide to open a database, it must contain a node.  Since this will be the first node in the database, it should be named MAIN.&lt;br /&gt;
&lt;br /&gt;
At the bottom of the file, on a separate line, add the @ENDNODE command.  This tells AmigaGuide that the current node ends here.  All nodes must contain an @ENDNODE command.&lt;br /&gt;
&lt;br /&gt;
This is what we have so far:&lt;br /&gt;
&lt;br /&gt;
    @DATABASE&lt;br /&gt;
    @NODE MAIN&lt;br /&gt;
    What is a user interface? This sweeping phrase covers all&lt;br /&gt;
            .&lt;br /&gt;
            .&lt;br /&gt;
            .&lt;br /&gt;
    complex character-based command strings.&lt;br /&gt;
    @ENDNODE&lt;br /&gt;
&lt;br /&gt;
The file is now an AmigaGuide database.  However, since the database has only one node and has no link points, the database will still appear as plain text.  Also, AmigaGuide will ghost all of the navigation buttons.  The database can be broken into smaller nodes if desired.  Normally such a short file would not need to be broken up, but it makes a good example.&lt;br /&gt;
&lt;br /&gt;
One important issue to consider while designing an AmigaGuide database is how to lay it out.  Some thought should go into the break-up of a document into manageable nodes, and how these nodes relate--and eventually link--to one another.  Each node should consist of information dealing with one topic and should contain links to other related nodes.&lt;br /&gt;
&lt;br /&gt;
Notice that the example text is about Intuition, but each paragraph discusses a different topic of Intuition.  The first paragraph is an overview followed by four paragraphs: one each on screens, windows, gadgets and menus.  This organization makes it convenient to make each paragraph a node with a table of contents in the beginning: &lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;    Intuition Table of Contents&lt;br /&gt;
&lt;br /&gt;
    Introduction&lt;br /&gt;
    Screens&lt;br /&gt;
    Windows&lt;br /&gt;
    Gadgets&lt;br /&gt;
    Menus&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Since the Table of Contents node is first, it is the MAIN node. The other paragraphs follow the MAIN node, each in their own separate node.  So as not to confuse AmigaGuide, each node within a database must have a different name.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;    @DATABASE&lt;br /&gt;
    @NODE MAIN &amp;quot;Intuition Table of Contents&amp;quot;&lt;br /&gt;
    Introduction&lt;br /&gt;
    Screens&lt;br /&gt;
    Windows&lt;br /&gt;
    Gadgets&lt;br /&gt;
    Menus&lt;br /&gt;
    @ENDNODE&lt;br /&gt;
&lt;br /&gt;
    @NODE Intro &amp;quot;Introduction&amp;quot;&lt;br /&gt;
    What is a user interface? This sweeping phrase...&lt;br /&gt;
    @ENDNODE&lt;br /&gt;
&lt;br /&gt;
    @NODE Screen &amp;quot;Screens&amp;quot;&lt;br /&gt;
    Intuition screens are the basis of any display...&lt;br /&gt;
    @ENDNODE&lt;br /&gt;
&lt;br /&gt;
    @NODE Window &amp;quot;Windows&amp;quot;&lt;br /&gt;
    Windows are rectangular display areas that open...&lt;br /&gt;
    @ENDNODE&lt;br /&gt;
&lt;br /&gt;
    @NODE Gadget &amp;quot;Gadgets&amp;quot;&lt;br /&gt;
    Gadgets are software controls symbolized by an...&lt;br /&gt;
    @ENDNODE&lt;br /&gt;
&lt;br /&gt;
    @NODE Menu &amp;quot;Menus&amp;quot;&lt;br /&gt;
    Menus are command and option lists associated...&lt;br /&gt;
    @ENDNODE&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When AmigaGuide loads the database above, AmigaGuide displays the MAIN node with the title string Intuition Table of Contents in the window&#039;s title bar.  As the user clicks the Browse buttons at the top of the AmigaGuide window, AmigaGuide steps through each node in the database, displaying each paragraph.  Notice that each node in the database uses the window title parameter.  As the Browse buttons step through the database displaying the different nodes in sequence, the AmigaGuide window title changes to match the title from the current node.&lt;br /&gt;
&lt;br /&gt;
An important limitation of the database above is the only way to access the different nodes is using the ``Browse&#039;&#039; button to step through them in the order they appear in the database.  The database still has no buttons within the nodes to link to other nodes.&lt;br /&gt;
&lt;br /&gt;
== Using Link Points ==&lt;br /&gt;
&lt;br /&gt;
The link point command is probably the most commonly used command in a database.  With it you can make a word in one node reference another node.  For example, in the Table of Contents node from the previous example, you can make each entry from the table into a button that references its respective node.&lt;br /&gt;
&lt;br /&gt;
The template for a link point is:&lt;br /&gt;
&lt;br /&gt;
    @{&amp;lt;label&amp;gt; &amp;lt;action command&amp;gt;}&lt;br /&gt;
&lt;br /&gt;
The label parameter is the word or phrase in a database that is made into a button, and the action command is the action AmigaGuide takes when the user clicks the button.  For our example, we want each topic in the table of contents to be a label and the action command for each to be a LINK command.  The LINK command loads and displays another node.&lt;br /&gt;
&lt;br /&gt;
    @{&amp;lt;label&amp;gt; LINK &amp;lt;name&amp;gt; &amp;lt;line#&amp;gt;}&lt;br /&gt;
&lt;br /&gt;
For example, if you change the word Introduction from the Table of Contents node into a link point it would look like this:&lt;br /&gt;
&lt;br /&gt;
    @{&amp;quot;Introduction&amp;quot; LINK Intro}&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;label&amp;gt; string must be in quotes.  If you load the database into AmigaGuide after making the change above, the word Introduction would appear as a button on the Table of Contents screen.  If the user clicks on the Introduction button, AmigaGuide displays the node named Intro.&lt;br /&gt;
&lt;br /&gt;
Unlike other AmigaGuide commands, link points do not need to start in the first column.  This makes it easy to indent a button from the left edge of the window and also to embed a button within a block of text.&lt;br /&gt;
&lt;br /&gt;
Link points can also link to nodes in other databases.  As an example, consider the following excerpt from the Intro node:&lt;br /&gt;
&lt;br /&gt;
  philosophy turned into software.  See the Amiga ROM Kernel Reference&lt;br /&gt;
  Manual: Libraries for more information.&lt;br /&gt;
&lt;br /&gt;
If an AmigaGuide database of Amiga ROM Kernel Reference Manual: Libraries was readily available,  it would be convenient if the word &#039;&#039;Libraries&#039;&#039; from the excerpt was a button, linking the word &#039;&#039;Libraries&#039;&#039; directly to the Libraries manual database.  If the Libraries manual database was named Libraries_Manual and it was in the current AmigaGuide path, to make the word Libraries from the Intro node into a link point that opens the Libraries_Manual database, change the excerpt above to the following:&lt;br /&gt;
&lt;br /&gt;
  philosophy turned into software.  See the Amiga ROM Kernel&lt;br /&gt;
  Reference Manual: @{&amp;quot;Libraries&amp;quot; LINK Libraries_Manual/Intro} for more information.&lt;br /&gt;
&lt;br /&gt;
In the example above, when the user selects the Libraries button, AmigaGuide will try to display the MAIN node from the database called Libraries_Manual.  AmigaGuide will first look for Libraries_Manual in the directory where the example database resides.  If it&#039;s not there, AmigaGuide searches through its path for the database.  Alternately, you can supply a full path name to Libraries_Manual.&lt;br /&gt;
&lt;br /&gt;
A link point can also be used to display a picture.  For example, to display an ILBM image of a Workbench screen from the Screen node, use the SYSTEM action command:&lt;br /&gt;
&lt;br /&gt;
    @{&amp;quot;Picture of a Workbench Screen&amp;quot; SYSTEM &amp;quot;sys:utilities/Display sys:Workbench.pic&amp;quot;}&lt;br /&gt;
&lt;br /&gt;
From the command above, when the user click the &#039;&#039;Picture of a Workbench Screen&#039;&#039; button, SYSTEM executes the Display utility. Display shows the ILBM file sys:Workbench.pic.  Because Display is merely a shell command, you can substitute your own ILBM viewer for Display.&lt;br /&gt;
&lt;br /&gt;
Below is the finished database with a few more interactive link points.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;  @DATABASE&lt;br /&gt;
  @NODE MAIN &amp;quot;Intuition Table of Contents&amp;quot;&lt;br /&gt;
  @{&amp;quot;Introduction&amp;quot; LINK Intro}&lt;br /&gt;
  @{&amp;quot;Screens&amp;quot; LINK Screen}&lt;br /&gt;
  @{&amp;quot;Windows&amp;quot; LINK Window}&lt;br /&gt;
  @{&amp;quot;Gadgets&amp;quot; LINK Gadget}&lt;br /&gt;
  @{&amp;quot;Menus&amp;quot; LINK Menu}&lt;br /&gt;
  @ENDNODE&lt;br /&gt;
&lt;br /&gt;
  @NODE Intro &amp;quot;Introduction&amp;quot;&lt;br /&gt;
  What is a user interface? This sweeping phrase covers all&lt;br /&gt;
  aspects of communication between the user and the computer.  It&lt;br /&gt;
  includes the innermost mechanisms of the computer and rises to&lt;br /&gt;
  the height of defining a philosophy to guide the interaction&lt;br /&gt;
  between human and machine.  Intuition is, above all else, a&lt;br /&gt;
  philosophy turned into software.  See the Amiga ROM Kernel&lt;br /&gt;
  Reference Manual: @{&amp;quot;Libraries&amp;quot; LINK Libraries_Manual/Intro} for more information.&lt;br /&gt;
  @ENDNODE&lt;br /&gt;
&lt;br /&gt;
  @NODE Screen &amp;quot;Screens&amp;quot;&lt;br /&gt;
  Intuition screens are the basis of any display Intuition can&lt;br /&gt;
  make.  Screens determine the fundamental characteristics of the&lt;br /&gt;
  display such as the resolution and palette and they set up the&lt;br /&gt;
  environment for multiple, overlapping @{&amp;quot;windows&amp;quot; LINK Window} that makes it&lt;br /&gt;
  possible for each application to have its own separate visual&lt;br /&gt;
  context.&lt;br /&gt;
&lt;br /&gt;
  @{&amp;quot;Picture of a Workbench Screen&amp;quot; SYSTEM sys:utilities/Display sys:Workbench.pic}&lt;br /&gt;
&lt;br /&gt;
  @ENDNODE&lt;br /&gt;
&lt;br /&gt;
  @NODE Window &amp;quot;Windows&amp;quot;&lt;br /&gt;
  Windows are rectangular display areas that open on @{&amp;quot;screens&amp;quot; LINK screen}.  The&lt;br /&gt;
  window acts as a virtual terminal allowing a program to interact&lt;br /&gt;
  with the user as if it had the entire display all to itself.&lt;br /&gt;
  Windows are moveable and can be positioned anywhere within the&lt;br /&gt;
  screen on which they exist.  Windows may also have a title and&lt;br /&gt;
  borders containing various @{&amp;quot;gadgets&amp;quot; LINK Gadget} for controlling the window.&lt;br /&gt;
  @ENDNODE&lt;br /&gt;
&lt;br /&gt;
  @NODE Gadget &amp;quot;Gadgets&amp;quot;&lt;br /&gt;
  Gadgets are software controls symbolized by an image that the&lt;br /&gt;
  user can operate with the mouse or keyboard.  They are the&lt;br /&gt;
  Amiga&#039;s equivalent of buttons, knobs and dials.&lt;br /&gt;
  @ENDNODE&lt;br /&gt;
&lt;br /&gt;
  @NODE Menu &amp;quot;Menus&amp;quot;&lt;br /&gt;
  Menus are command and option lists associated with an&lt;br /&gt;
  application @{&amp;quot;window&amp;quot; LINK Window} that the user can bring into view at any&lt;br /&gt;
  time.  These lists provide the user with a simple way to access&lt;br /&gt;
  features of the application without having to remember or enter&lt;br /&gt;
  complex character-based command strings.&lt;br /&gt;
  @ENDNODE&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Although this is a small sample and only a few basic commands are used, it is a good start to making your own AmigaGuide database.&lt;br /&gt;
&lt;br /&gt;
== Troubleshooting ==&lt;br /&gt;
&lt;br /&gt;
To make it easier to create a bug-free database, below is a list of common mistakes made when editing an AmigaGuide database.&lt;br /&gt;
&lt;br /&gt;
As with any type of programming, errors are bound to crop up.  One of the most common mistakes is spelling errors.  Always double check your spelling of commands.  Also, make sure all commands that should begin in the first column do so.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Symptom:  AmigaGuide displays a database as a text file.  For example, instead of a button, AmigaGuide displays the link point command that was supposed to display the button.&lt;br /&gt;
*Cure: AmigaGuide does not think the file is an AmigaGuide database. Check that the first line of the file is the @DATABASE command and that it starts in the first column.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Symptom: When displaying a database node, AmigaGuide displays nothing in its window.&lt;br /&gt;
*Cure: Either the @ENDNODE command is not present in the node or the @ENDCODE command does not start in the first column.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Symptom: AmigaGuide does not display a button or its label.&lt;br /&gt;
*Cure: The &amp;lt;label&amp;gt; parameter in the link point is missing or not enclosed in quotes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Symptom: When the user selects a button, AmigaGuide flashes the screen and displays the error message &amp;quot;Couldn&#039;t locate &amp;lt;node&amp;gt;&amp;quot;.&lt;br /&gt;
*Cure: AmigaGuide cannot locate the node specified in the button&#039;s link point command.  If the link point command points to a node in another database, the database must be in the AmigaGuide path or the node must contain the full path name to the database.  The link point command also require a NODE name as the last parameter in the path separated by a slant (/).  If the file is only text and not an AmigaGuide database, its path name should end with &#039;&#039;&#039;/MAIN&#039;&#039;&#039;.  If a node or file has any spaces in its name, the path name must be enclosed within quotes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Symptom: AmigaGuide flashes the screen when a button is selected but displays no error message.&lt;br /&gt;
*Cure: AmigaGuide does not recognize the &amp;lt;action command&amp;gt; parameter in the link point, or AmigaGuide cannot locate the specified node (see the cure above).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Symptom: AmigaGuide does not fully display a button.&lt;br /&gt;
*Cure: Check that all of the link points end with a closing brace (}). Note that there is a bug in AmigaGuide that can crash the system if a link point does not end with a closing brace.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Symptom: AmigaGuide will not load a database and displays a &amp;quot;Can&#039;t find Node&amp;quot; requester.&lt;br /&gt;
*Cure: All databases must contain at least one node.  If the file is short, all the text can be in one node called &#039;&#039;&#039;MAIN&#039;&#039;&#039;.  If you do not wish to make the file a database at all, remove the @DATABASE command.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Symptom: AmigaGuide does not allow the the user to browse the database to its end.  It either stops browsing before reaching the last node, or it gets caught in an endless loop, cycling through a number of nodes.&lt;br /&gt;
*Cure: At least two nodes within a single database have the same name. Every node must have a different name unless they are in separate databases.&lt;/div&gt;</summary>
		<author><name>James Jacobs</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=AmigaOS_Versions&amp;diff=12097</id>
		<title>AmigaOS Versions</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=AmigaOS_Versions&amp;diff=12097"/>
		<updated>2021-10-21T07:13:02Z</updated>

		<summary type="html">&lt;p&gt;James Jacobs: Added V46 and V47&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The version number reflects a revision of the system software. The chart below lists the specific AmigaOS release versions that system libraries versions correspond to:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Version !! Release !! Description&lt;br /&gt;
|-&lt;br /&gt;
| 27.3 || Kickstart 0.7 || First AmigaOS version shown at Consumer Electronics Show in 1985. This version is obsolete.&lt;br /&gt;
|-&lt;br /&gt;
| 29 || Kickstart 0.9 || This is an internal AmigaOS version. This version is obsolete.&lt;br /&gt;
|-&lt;br /&gt;
| 30 || Kickstart 1.0 || This revision is obsolete.&lt;br /&gt;
|-&lt;br /&gt;
| 31 || Kickstart 1.1 || This was an NTSC only release and is obsolete.&lt;br /&gt;
|-&lt;br /&gt;
| 32 || Kickstart 1.1 || This was a PAL only release and is obsolete.&lt;br /&gt;
|-&lt;br /&gt;
| 33 || Kickstart 1.2 || This is the oldest revision of the OS.&lt;br /&gt;
|-&lt;br /&gt;
| 34 || Kickstart 1.3 || This is almost the same as release 1.2 except it has an Autobooting expansion.library&lt;br /&gt;
|-&lt;br /&gt;
| 35 || || This is a special RAM-loaded version of the 1.3 revision, except that it knows about the &#039;&#039;A2024&#039;&#039; display modes. No application should need this library unless they need to open an &#039;&#039;A2024&#039;&#039; display mode under 1.3.&lt;br /&gt;
|-&lt;br /&gt;
| 36 || Kickstart 2.0 || This is the original Release 2 revision that was initially shipped on early &#039;&#039;Amiga 3000&#039;&#039; models.&lt;br /&gt;
|-&lt;br /&gt;
| 37 || Kickstart 2.04 || This is the general Release 2 revision for all Amiga models.&lt;br /&gt;
|-&lt;br /&gt;
| 38 || Kickstart 2.1 || This is an updated Release 2 revision for &#039;&#039;Amiga 600&#039;&#039; models.&lt;br /&gt;
|-&lt;br /&gt;
| 39 || Kickstart 3.0 || This is the original Release 3 revision hat was initially shipped on &#039;&#039;Amiga 1200&#039;&#039; and &#039;&#039;Amiga 4000&#039;&#039; models.&lt;br /&gt;
|-&lt;br /&gt;
| 40 || Kickstart 3.1 || This is the original Release 3 revision for all Amiga models.&lt;br /&gt;
|-&lt;br /&gt;
| 41 || Kickstart 3.1 || This is version number which was reserved for the Japanese locale version of AmigaOS 3.1, with multi-byte character support (never completed).&lt;br /&gt;
|-&lt;br /&gt;
| 42 ||  || This is version number for some AmigaOS&#039; modules of an internal alpha revision (early 1993).&lt;br /&gt;
|-&lt;br /&gt;
| 43 || Kickstart 3.2 || This is the original Release 3 revision for Amiga Walker model (never completed). This revision was used for stuff done by/for Amiga Technologies/Amiga International (1995).&lt;br /&gt;
|-&lt;br /&gt;
| 44 || Kickstart 3.5 || This is an update to Release 3 revision for all Amiga models.&lt;br /&gt;
|-&lt;br /&gt;
| 45 || Kickstart 3.9 || This is an update to Release 3 revision for all Amiga models.&lt;br /&gt;
|-&lt;br /&gt;
| 46 || Kickstart 3.1.4 || This is an update to Release 3 revision for all Amiga models.&lt;br /&gt;
|-&lt;br /&gt;
| 47 || Kickstart 3.2 || This is an update to Release 3 revision for all Amiga models.&lt;br /&gt;
|-&lt;br /&gt;
| 50 || Kickstart 4.0 || This is the general Release 4 revision for the new &#039;&#039;AmigaOne&#039;&#039; range (Developer PreRelease).&lt;br /&gt;
|-&lt;br /&gt;
| 51 || Kickstart 4.0 || This is an update to Release 4 revision for the new &#039;&#039;AmigaOne&#039;&#039; range (Official Release from Update 1).&lt;br /&gt;
|-&lt;br /&gt;
| 52 || Kickstart 4.0 || This is an update to Release 4 revision to include support for PPC equipped classic Amiga models.&lt;br /&gt;
|-&lt;br /&gt;
| 53 || Kickstart 4.1 || This is an update to Release 4 revision for all supported PPC models.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>James Jacobs</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Wiki_Author_Credits&amp;diff=9856</id>
		<title>Wiki Author Credits</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Wiki_Author_Credits&amp;diff=9856"/>
		<updated>2018-11-19T10:55:45Z</updated>

		<summary type="html">&lt;p&gt;James Jacobs: Added missing link&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The following is a list of known contributors to this wiki:&lt;br /&gt;
&lt;br /&gt;
* Adam Levin&lt;br /&gt;
* Alexandre Balaban&lt;br /&gt;
* [http://amigaak.org.nz/ Amiga Auckland]&lt;br /&gt;
* Andy Finkel&lt;br /&gt;
* Bart Whitebook&lt;br /&gt;
* Bill Borsari&lt;br /&gt;
* Bill Koester&lt;br /&gt;
* Bob Burns&lt;br /&gt;
* Bob Pariseau&lt;br /&gt;
* Bruce Barrett&lt;br /&gt;
* Bryce Nesbitt&lt;br /&gt;
* Carl Sassenrath&lt;br /&gt;
* Carolyn Scheppner&lt;br /&gt;
* Chris Green&lt;br /&gt;
* Chris Ludwig&lt;br /&gt;
* Chris Raymond&lt;br /&gt;
* Dale Luck&lt;br /&gt;
* Dan Baker&lt;br /&gt;
* [http://gtmooya.blogspot.com/ Daniel Hutchinson]&lt;br /&gt;
* Daniel Jedlicka&lt;br /&gt;
* Darius Taghavy&lt;br /&gt;
* Darren Greenwald&lt;br /&gt;
* Dave Berezowski&lt;br /&gt;
* Dave Lucas&lt;br /&gt;
* David Junod&lt;br /&gt;
* David Miller&lt;br /&gt;
* Don Cox&lt;br /&gt;
* Douglas Stastny&lt;br /&gt;
* Eric Cotton&lt;br /&gt;
* Ewout Walraven&lt;br /&gt;
* Frank Bunton, for his [http://aminet.net/package/docs/help/adosbegin AmigaDOS guide]&lt;br /&gt;
* Hans-Joerg Frieden&lt;br /&gt;
* [http://amigan.1emu.net/ James Jacobs]&lt;br /&gt;
* [http://www.janneperaaho.arkku.net/ Janne Peräaho]&lt;br /&gt;
* Jerry Hartzler&lt;br /&gt;
* Jez San&lt;br /&gt;
* Jim Mackraz&lt;br /&gt;
* Joe Katz&lt;br /&gt;
* John Orr&lt;br /&gt;
* John Wiederhirn&lt;br /&gt;
* Karl Churchill&lt;br /&gt;
* Ken Farinsky&lt;br /&gt;
* Kevin Klop&lt;br /&gt;
* Larry Hildenbrand&lt;br /&gt;
* Leo Schwab&lt;br /&gt;
* [https://sites.google.com/site/takeaprogrammertolunch/ Lyle Hazelwood]&lt;br /&gt;
* Mark Barton&lt;br /&gt;
* Mark Ricci&lt;br /&gt;
* [http://wandel.ca/ Markus Wandel]&lt;br /&gt;
* Martin Taillefer&lt;br /&gt;
* Michael Sinz&lt;br /&gt;
* Nancy Rains&lt;br /&gt;
* Neil Kafferkey&lt;br /&gt;
* Neil Katin&lt;br /&gt;
* Olaf Barthel&lt;br /&gt;
* Paul Higginbottom&lt;br /&gt;
* Paul Sadlik&lt;br /&gt;
* Peter Cherna&lt;br /&gt;
* Philippe Ferrucci&lt;br /&gt;
* R.J. Mical&lt;br /&gt;
* Randell Jesup&lt;br /&gt;
* Ray Brand&lt;br /&gt;
* Rob Cranley&lt;br /&gt;
* Rob Peck&lt;br /&gt;
* Rob Wyesham&lt;br /&gt;
* Roman Kargin&lt;br /&gt;
* Sam Dicker&lt;br /&gt;
* Simon Archer&lt;br /&gt;
* Spencer Shanson&lt;br /&gt;
* Stan Shepard&lt;br /&gt;
* Steve Beats&lt;br /&gt;
* [http://www.solie.ca Steven Solie]&lt;br /&gt;
* Stuart Ferguson&lt;br /&gt;
* Susan Deyl&lt;br /&gt;
* Thomas Frieden&lt;br /&gt;
* Tom Pohorsky&lt;br /&gt;
* Tom Rokicki&lt;/div&gt;</summary>
		<author><name>James Jacobs</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=AmiWest_Lesson_8&amp;diff=4874</id>
		<title>AmiWest Lesson 8</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=AmiWest_Lesson_8&amp;diff=4874"/>
		<updated>2013-02-27T06:43:23Z</updated>

		<summary type="html">&lt;p&gt;James Jacobs: Fixed typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;An AmigaOS innovation was the nearly universal support for high level interprocess and scripted communications using &amp;quot;ARexx ports&amp;quot;, &amp;quot;ARexx messages&amp;quot; and the interpreted &amp;quot;ARexx&amp;quot; language.  &lt;br /&gt;
&lt;br /&gt;
By providing and using ARexx ports, applications are able to send messages to each other.  ARexx scripts can also be run by the user or applications providing a level of control that far exceeds simple &amp;quot;recorded&amp;quot; macros found elswhere.  As new interpreted languages have been ported to AmigaOS, some - like Python - have been adapted to mimic the ARexx language&#039;s ability to send and receive messages. &lt;br /&gt;
&lt;br /&gt;
In this text we will explore the process of having an application to open an ARexx port, send and receive messages and to be able to run ARexx scripts (as application &amp;quot;macros&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==Initialization==&lt;br /&gt;
&lt;br /&gt;
Like much of the current AmigaOS, the support of ARexx operations within C programs has been modernized and simplified using the BOOPSI style of object oriented methods.  Under AmigaOS4, the requirements to open specific libraries has been further automated with the OS4 SDK.  To use ARexx messaging within an application, we need to initialize a few things:&lt;br /&gt;
:* Create a BOOPSI  &amp;quot;ARexx Object&amp;quot;.&lt;br /&gt;
:* Create an hook to a function to receive responses.&lt;br /&gt;
:* Create the function called with responses.&lt;br /&gt;
&lt;br /&gt;
===Obtaining an ARexx Object===&lt;br /&gt;
&lt;br /&gt;
After confirming the &#039;&#039;&#039;arexx.library&#039;&#039;&#039; has been automatically opened, one of the first steps to using ARexx involves calling the BOOPSI &#039;&#039;&#039;NewObject&#039;&#039;&#039; function.  This general BOOPSI function uses the following list of &#039;&#039;&#039;tags&#039;&#039;&#039; to create an ARexx &amp;quot;object&amp;quot;, an ARexx port for your application and get it ready to send/receive messages:&lt;br /&gt;
&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Tag Name&#039;&#039;&#039; &lt;br /&gt;
|style=&amp;quot;width: 20%;&amp;quot;|&#039;&#039;&#039;Variable Type&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Required?&#039;&#039;&#039;||&#039;&#039;&#039;Notes&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|AREXX_HostName||CONST_STRPTR||Yes, unless Msg Port is used||Sets the &amp;quot;host name&amp;quot; of your application&#039;s ARexx port.  &lt;br /&gt;
|-&lt;br /&gt;
|AREXX_NoSlot ||BOOL||No||Determines whether a port counter number is added to the host port name.  DEFAULT: FALSE = a number will be appended to the port name.&lt;br /&gt;
|-&lt;br /&gt;
|AREXX_DefExtension||CONST_STRPTR||No||Filename extension that will get appended when calling a macro script.  DEFAULT: &amp;quot;rexx&amp;quot;.&lt;br /&gt;
|-&lt;br /&gt;
|AREXX_Commands||struct ARexxCmd *||Only for receiving commands||A structure containing a table of ARexx commands your application understands.  More on this below.&lt;br /&gt;
|-&lt;br /&gt;
|AREXX_ErrorCode||uint32 *||No||A error code pointer reflecting any issues with creating the new ARexx object.&lt;br /&gt;
|-&lt;br /&gt;
|AREXX_ReplyHook||struct Hook *||Yes for replies, unless Msg Port is used||A function hook structure for a function that will be called if your app receives a message or reply to a sent message.&lt;br /&gt;
|-&lt;br /&gt;
|AREXX_MsgPort||struct MsgPort *||No||A message port pointer to be used instead of creating and receiving messages in an ARexx port.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Naturally, how these tags are used will depend on the intended functions of the application.  Obviously, an app that will only send messages will not need to define a list of commands received.  Some apps might want to set the &amp;quot;AREXX_NoSlot&amp;quot; tag to &amp;quot;TRUE&amp;quot; if they want to make sure they will be the only port with a name and it will require yet more code to handle the possible situation if that port name is already in use.  The SDK &amp;quot;autodocs&amp;quot; can provide more detail on these tags.&lt;br /&gt;
&lt;br /&gt;
The following simple code example uses these tags where an application only expects to send ARexx messages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
     Object *arexx_obj;&lt;br /&gt;
     STATIC struct Hook reply_hook;&lt;br /&gt;
     char port_name[40];&lt;br /&gt;
     uint32 errorCode;&lt;br /&gt;
     arexx_obj = IIntuition-&amp;gt;NewObject(NULL, &amp;quot;arexx.class&amp;quot;,&lt;br /&gt;
          AREXX_HostName, &amp;quot;AREXX_SENDER&amp;quot;,	&lt;br /&gt;
          AREXX_NoSlot, TRUE,&lt;br /&gt;
          AREXX_ErrorCode, &amp;amp;errorCode,	&lt;br /&gt;
          AREXX_ReplyHook, &amp;amp;reply_hook,&lt;br /&gt;
     TAG_DONE);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
If the &#039;&#039;&#039;NewObject&#039;&#039;&#039; function is successful, it will return a pointer to the new ARexx Object.  If the function fails, we can check the contents of the &amp;quot;errorCode&amp;quot; variable against these predefined error codes:&lt;br /&gt;
&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|RXERR_NO_COMMAND_LIST||||No command list was provided.&lt;br /&gt;
|-&lt;br /&gt;
|RXERR_NO_PORT_NAME||||No host base name was provided.&lt;br /&gt;
|-&lt;br /&gt;
|RXERR_PORT_ALREADY_EXISTS||||The class  was unable to create a unique name of the base name you provided.&lt;br /&gt;
|-&lt;br /&gt;
|RXERR_OUT_OF_MEMORY||||Not enough free memory.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===A Reply Hook===&lt;br /&gt;
&lt;br /&gt;
Virtually any application will have incoming messages to deal with.  For any message sent, the recipient must send a reply.  So a reply hook and function would be used for not only messages sent by other applications, but also responses to messages sent from our application.&lt;br /&gt;
&lt;br /&gt;
To do so, most applications will also define a pointer to an AmigaOS &#039;&#039;&#039;Hook&#039;&#039;&#039; structure (&amp;quot;reply_hook&amp;quot;) to receive incoming messages and responses to sent messages.  This standard structure allows us to define a function in our application that will be run when our application receives messages or responses.  Once we&#039;ve successfully obtained an ARexx object giving us an ARexx port, we would set up the hook function like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
STATIC struct Hook reply_hook;&lt;br /&gt;
[...]&lt;br /&gt;
      reply_hook.h_Entry    = (HOOKFUNC)reply_callback;	// pointer to function name to be called&lt;br /&gt;
      reply_hook.h_SubEntry = NULL;&lt;br /&gt;
      reply_hook.h_Data     = NULL;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this excerpt, &amp;quot;reply_callback&amp;quot; is the name of a C function we create that will be called when an ARexx message or response is received.&lt;br /&gt;
&lt;br /&gt;
===Reply Function===&lt;br /&gt;
&lt;br /&gt;
While the function we create to be called by the &amp;quot;reply hook&amp;quot; will be passed a number of arguments, we are only concerned with the ARexx message passed to our function.  This &amp;quot;RexxMessage&amp;quot; structure has the following basic structure:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
struct RexxMsg&lt;br /&gt;
{&lt;br /&gt;
     struct Mesage     rm_Node;     /* Exec message structure */&lt;br /&gt;
     APTR     rm_TaskBlock;     /* private global structure */&lt;br /&gt;
     APTR     rm_LibBase;     /* private library base */&lt;br /&gt;
     int32     rm_Action;     /* command action code */&lt;br /&gt;
     int32     rm_Result1;     /* primart result (return code) */&lt;br /&gt;
     int32     rm_Result2;     /* secondary result */&lt;br /&gt;
     STRPTR     rm_Args[16];     /* argument block */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Additional &amp;quot;extension fields&amp;quot; may also be passed within the RexxMessage structure when starting an ARexx program.  Those are defined in the CBM AmigaMail articles and CBM &amp;quot;ARexx Programmers Guide&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
In most cases, applications passing typical messages will be focused on the two &amp;quot;Result&amp;quot; fields.  The first value (&amp;quot;Result1&amp;quot;) will contain an integer where zero means there was no error or it will have an error code number (&amp;gt;0).  In the cases where there is no error, the second field (&amp;quot;Result2&amp;quot;) will contain a pointer to any result string sent with the message (or zero if none).&lt;br /&gt;
&lt;br /&gt;
The following is an example of a simple implementation of a reply function that just prints out the contents of received messages:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
STATIC VOID reply_callback(struct Hook *hook UNUSED, Object *o UNUSED, struct RexxMsg *rxm)&lt;br /&gt;
{&lt;br /&gt;
     IDOS-&amp;gt;Printf(&amp;quot;Result1 =&amp;gt;%ld&amp;lt;\n&amp;quot;, rxm-&amp;gt;rm_Result1);&lt;br /&gt;
     if (rxm-&amp;gt;rm_Result1 == 0)&lt;br /&gt;
          IDOS-&amp;gt;Printf(&amp;quot;Result2 =&amp;gt;%s&amp;lt;\n&amp;quot;, (CONST_STRPTR)rxm-&amp;gt;rm_Result2);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Sending ARexx Messages==&lt;br /&gt;
&lt;br /&gt;
Once we have initialized a BOOPSI ARexx Object and the reply_hook structure, we are then ready to try to send ARexx messages.  Of course, sending messages can be broken into a few steps:&lt;br /&gt;
&lt;br /&gt;
:* Finding the ARexx port to send the message to.&lt;br /&gt;
:* Sending the ARexx message.&lt;br /&gt;
:* Waiting for a response to our message.&lt;br /&gt;
:* Handling the response.&lt;br /&gt;
&lt;br /&gt;
===Finding the Target Port===&lt;br /&gt;
&lt;br /&gt;
To send a message, you have to have a valid name of the target ARexx message port.  With the port name in a string, we can use the AmigaOS &#039;&#039;&#039;FindPort&#039;&#039;&#039; function to determine if the port exists.  To prevent ports from appearing or disappearing during this search, calling &#039;&#039;&#039;FindPort&#039;&#039;&#039; is &amp;quot;wrapped&amp;quot; with &#039;&#039;&#039;Forbid&#039;&#039;&#039;/&#039;&#039;&#039;Permit&#039;&#039;&#039; functions to interupt multitasking.  Obvbiously, this interuption should be kept as short as possible.&lt;br /&gt;
&lt;br /&gt;
The following code excerpt would search for the Workbench ARexx port:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
     CONST_STRPTR port_name = &amp;quot;WORKBENCH&amp;quot;;&lt;br /&gt;
     IExec-&amp;gt;Forbid();&lt;br /&gt;
     if (IExec-&amp;gt;FindPort(port_name))&lt;br /&gt;
     {&lt;br /&gt;
          Exec-&amp;gt;Permit();&lt;br /&gt;
          IDOS-&amp;gt;Printf(&amp;quot;Found WORKBENCH ARexx port!\n&amp;quot;);&lt;br /&gt;
          // Here we can go on to send a message.&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
          Exec-&amp;gt;Permit();&lt;br /&gt;
          IDOS-&amp;gt;Printf(&amp;quot;WORKBENCH ARexx port not found.\n&amp;quot;);&lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, we make sure to reenable multitasking as quickly as possible, regardless of whether the port name was found.  As with any error trapping, any application should have a graceful way of handling an issue like a missing ARexx port and letting the user deal with the occurence.&lt;br /&gt;
&lt;br /&gt;
===Sending the Message===&lt;br /&gt;
&lt;br /&gt;
After all our steps of initialization and verifying our target ARexx port, sending our ARexx message is a single call of the BOOPSI &#039;&#039;&#039;IDoMethod&#039;&#039;&#039; function.  With the &amp;quot;AM_EXECUTE&amp;quot; method, the &#039;&#039;&#039;IDoMethod&#039;&#039;&#039; function uses the ARexx object, the method name and the following parameters:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Argument Name&#039;&#039;&#039; &lt;br /&gt;
|style=&amp;quot;width: 20%;&amp;quot;|&#039;&#039;&#039;Variable Type&#039;&#039;&#039; &lt;br /&gt;
|&#039;&#039;&#039;Notes&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|MethodID||uint32||The arexx class &amp;quot;method&amp;quot;, in this case &amp;quot;AM_EXECUTE&amp;quot;.  &lt;br /&gt;
|-&lt;br /&gt;
|ape_CommandString||CONST_STRPTR||The command and arguments to be executed - either sent to an ARexx port or the ARexx host.&lt;br /&gt;
|-&lt;br /&gt;
|ape_PortName||CONST_STRPTR||The name of the ARexx port to send the message to, if not the ARexx host.&lt;br /&gt;
|-&lt;br /&gt;
|ape_RC||int32 *||Primary result code if the message was sent to the ARexx host.&lt;br /&gt;
|-&lt;br /&gt;
|ape_RC2||uint32 *||Secondary result code if the message was sent to the ARexx host.&lt;br /&gt;
|-&lt;br /&gt;
|ape_Result||STRPTR *||The result string if the message was sent to the ARexx host.&lt;br /&gt;
|-&lt;br /&gt;
|ape_IO||BPTR||Alternate IO channel pointer if an executed script is to use a different IO channel.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
To read more about these parameters, refer to the &amp;quot;arexx_cl&amp;quot; autodocs.&lt;br /&gt;
&lt;br /&gt;
To send a message, we only need to add the target port name and our message string, as follows:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
     CONST_STRPTR cmd = &amp;quot;HELP&amp;quot;;&lt;br /&gt;
     int32 RC,RC2;&lt;br /&gt;
     char result[100];&lt;br /&gt;
     IIntuition-&amp;gt;IDoMethod(arexx_obj,AM_EXECUTE,cmd,port_name,NULL,NULL,NULL,NULL);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see all the return &amp;amp; result arguments are given NULL&#039;s when we send an ARexx message.  Sending ARexx messages is considered &amp;quot;Asynchronous&amp;quot; - in other words, our application will not get an immediate response and will continue operating in the meantime.&lt;br /&gt;
&lt;br /&gt;
===Waiting for and Handling Replies===&lt;br /&gt;
&lt;br /&gt;
When a response to our sent message is received, it will arrive with an AmigaOS &#039;&#039;&#039;signal&#039;&#039;&#039; to our application&#039;s message port that it has received an ARexx message.  Like many other signals to applications (Intuition, control code signals, etc.) we need to obtain a mask for receiving ARexx events.   Then we can combine all those signals together and call the &#039;&#039;&#039;Wait&#039;&#039;&#039; function to put our app asleep, waiting for those events.&lt;br /&gt;
&lt;br /&gt;
When an event matching any of the &#039;&#039;&#039;Wait&#039;&#039;&#039; function&#039;s set of signals occurs, our application will be woken up. Then we have to determine if it was ARexx message that woke up our app and handle that event.  At that point, we use the BOOPSI &amp;quot;IDoMethod&amp;quot; function again, this time with the &amp;quot;AM_HANDLEEVENT&amp;quot; method.  This will cause the reply_hook &amp;amp; function (defined above) to be called to handle the incoming message.&lt;br /&gt;
&lt;br /&gt;
Here is some example code of waiting for handling an incoming ARexx message:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
     uint32 rxsig = 0, signal;&lt;br /&gt;
     IIntuition-&amp;gt;GetAttr(AREXX_SigMask, arexx_obj, &amp;amp;rxsig);&lt;br /&gt;
     signal = IExec-&amp;gt;Wait(rxsig | SIGBREAKF_CTRL_C);&lt;br /&gt;
     if (signal &amp;amp; rxsig)&lt;br /&gt;
     {&lt;br /&gt;
           IIntuition-&amp;gt;IDoMethod(arexx_obj, AM_HANDLEEVENT);&lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As configured, this &#039;&#039;&#039;Wait&#039;&#039;&#039; function will put our application to sleep until it receives either an ARexx message or &amp;quot;control-c&amp;quot; signal.  Of course, a complete application would also check for and respond to a possible &amp;quot;control-c&amp;quot; signal (or anything else) and respond accordingly.&lt;br /&gt;
&lt;br /&gt;
==Receiving ARexx Messages==&lt;br /&gt;
&lt;br /&gt;
Creating an application for receiving designated ARexx commands is handled in a similar fashion as dealing with replies to sent messages (above), except the &amp;quot;known&amp;quot; commands are defined in the application code and a function is designated to be called when each of those commands is received.&lt;br /&gt;
&lt;br /&gt;
To start with, if we are create an application meant to receive ARexx commands then we will have to adjust our &#039;&#039;&#039;NewObject&#039;&#039;&#039; request for a new ARexx Object.  In this case, that code might look like:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
     arexx_obj = IIntuition-&amp;gt;NewObject(NULL, &amp;quot;arexx.class&amp;quot;,&lt;br /&gt;
          AREXX_HostName, &amp;quot;AREXX-RECEIVER&amp;quot;,	&lt;br /&gt;
          AREXX_NoSlot, TRUE,&lt;br /&gt;
          AREXX_ErrorCode, &amp;amp;errorCode,&lt;br /&gt;
          AREXX_Commands, Commands,&lt;br /&gt;
          AREXX_NoSlot, TRUE,&lt;br /&gt;
     TAG_DONE);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The pertinent difference being that we are now defining &amp;quot;AREXX_Command&amp;quot; instead of &amp;quot;AREXX_ReplyHook&amp;quot; in the above sample.&lt;br /&gt;
&lt;br /&gt;
===Defining Commands to be Received===&lt;br /&gt;
&lt;br /&gt;
In an application where we will be receiving a number of predefined commands, we set up an array of structures that will define those commands, the functions to be called when those command are received and what arguments are accepted.  Here are the fields used:&lt;br /&gt;
&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Field Name&#039;&#039;&#039; ||&#039;&#039;&#039;Variable Type&#039;&#039;&#039; ||&#039;&#039;&#039;Notes&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|ac_Name||CONST_STRPTR||The command name sent. Usually all uppercase.  &lt;br /&gt;
|-&lt;br /&gt;
|ac_ID||uint16||A unique identifier number.&lt;br /&gt;
|-&lt;br /&gt;
|ac_Func||*()(struct ARexxCmd *, struct RexxMsg *)||A pointer to a function that will be called when this command is received.&lt;br /&gt;
|-&lt;br /&gt;
|ac_ArgTemplate||CONST_STRPTR||An AmigaDOS style template for the arrguments expected with this command.&lt;br /&gt;
|-&lt;br /&gt;
|ac_Flags||uint32||Future argument, to be set to NULL now.&lt;br /&gt;
|-&lt;br /&gt;
|ac_ArgList||uint32 *||With Messages:  Result of ReadArgs on arguments received based on template above.&lt;br /&gt;
|-&lt;br /&gt;
|ac_RC||uint32||With Messages: Primary Result variable.&lt;br /&gt;
|-&lt;br /&gt;
|ac_RC2||uint32||With Messages:  Secondary result variable. This will not be set unless RC &amp;gt; 0.&lt;br /&gt;
|-&lt;br /&gt;
|ac_Result||STRPTR||With Messages:  Result string.  This will not be set if RC &amp;gt; 0.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The last four fields of this structure are all set to NULL and zero values when the commands are defined.  They will only be used when those commands are used to interact with the incoming message and the sender.&lt;br /&gt;
&lt;br /&gt;
In the follow code sample, you can see where we define just such an array of &amp;quot;ARexxCmd&amp;quot; structures.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
     STATIC struct ARexxCmd Commands[] =&lt;br /&gt;
     {&lt;br /&gt;
          {&amp;quot;NAME&amp;quot;,    0, rexx_Name,    NULL,       0, NULL, 0, 0, NULL},&lt;br /&gt;
          {&amp;quot;VERSION&amp;quot;, 1, rexx_Version, NULL,       0, NULL, 0, 0, NULL},&lt;br /&gt;
          {&amp;quot;QUIT&amp;quot;,    2, rexx_Quit,    NULL,       0, NULL, 0, 0, NULL},&lt;br /&gt;
          {&amp;quot;SEND&amp;quot;,    3, rexx_Send,    &amp;quot;TEXT/F&amp;quot;,   0, NULL, 0, 0, NULL},&lt;br /&gt;
          {&amp;quot;DATE&amp;quot;,    4, rexx_Date,    &amp;quot;SYSTEM/S&amp;quot;, 0, NULL, 0, 0, NULL},&lt;br /&gt;
          {&amp;quot;HELP&amp;quot;,    5, rexx_Help,    NULL,       0, NULL, 0, 0, NULL},&lt;br /&gt;
          {NULL, 0, NULL, NULL, 0, NULL, 0, 0, NULL}&lt;br /&gt;
     };&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As you can see, two of the commands (&amp;quot;SEND&amp;quot; and &amp;quot;DATE&amp;quot;) are configured to also accept arguments.  The formatting of the &amp;quot;ArgTemplate&amp;quot; field should follow that used by the &#039;&#039;&#039;ReadArgs&#039;&#039;&#039; function.  Please see the autodocs on &#039;&#039;&#039;ReadArgs&#039;&#039;&#039; for more information on how the template is parsed.&lt;br /&gt;
&lt;br /&gt;
===Waiting for Messages===&lt;br /&gt;
&lt;br /&gt;
The process for waiting for incoming ARexx messages with commands is generally the same as it was in the above example waiting for replies to sent commands.  We just obtain the mask ARexx messages, combine it with any other signal masks and call the AmigaOS &#039;&#039;&#039;Wait&#039;&#039;&#039; function.  Again when the application is woken up, we check to see when an ARexx message was received and then call the &#039;&#039;&#039;IDoMethod&#039;&#039;&#039; with the &amp;quot;AM_HANDLEEVENT&amp;quot; method.&lt;br /&gt;
&lt;br /&gt;
The difference with sent message responses is that when the &#039;&#039;&#039;IDoMethod&#039;&#039;&#039; function is called with commands, the designated function is called for command received (as set in the Commands array above).  For example, if the &amp;quot;SEND&amp;quot; command is received, the &amp;quot;rexx_Send&amp;quot; function will be called.&lt;br /&gt;
&lt;br /&gt;
===Functions to Handle Commands===&lt;br /&gt;
&lt;br /&gt;
When the &#039;&#039;&#039;IDoMethod&#039;&#039;&#039; function is called with &amp;quot;AM_HANDLEEVENT&amp;quot;, the ARexx class will determine which command was received and then call the appropriate function and provide the following arguments:&lt;br /&gt;
&lt;br /&gt;
::STATIC VOID &#039;&#039;&#039;&amp;lt;function name&amp;gt;&#039;&#039;&#039; (struct ARexxCmd *, struct RexxMsg)&lt;br /&gt;
&lt;br /&gt;
As you can see, the ARexx class passes two structures to the function.  The first structure is the same format as that configured in the commands array above and we can use it to read incoming data and send things back to the message sender.  The pertinent fields are as follows:&lt;br /&gt;
&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Field Name&#039;&#039;&#039; ||&#039;&#039;&#039;Variable Type&#039;&#039;&#039; ||&#039;&#039;&#039;Usage&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|ac_ArgList||uint32 *||An array with the results of ReadArgs filtering the arguments in the sent message.  Read these elements to obtain data sent with the message.&lt;br /&gt;
|-&lt;br /&gt;
|ac_RC||uint32||This argument is the &amp;quot;primary result variable&amp;quot; and is returned to the message sending application to indicate success, warning, errors, etc.&lt;br /&gt;
|-&lt;br /&gt;
|ac_RC2||uint32||This is the &amp;quot;secondary result variable&amp;quot; and will only be used if the RC variable is set  &amp;gt;0.&lt;br /&gt;
|-&lt;br /&gt;
|ac_Result||STRPTR||This is the &amp;quot;result string&amp;quot; that can be set by our application and will be sent back to the sending app if the above RC variable is = 0.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Typically, &amp;quot;ArgList&amp;quot; entries (like &amp;quot;ArgList[0]&amp;quot;) will be read for incoming command parameters.  Bear in mind, the contents of those arguments are parsed and filtered by the &#039;&#039;&#039;ReadArgs&#039;&#039;&#039; function using the template set in the commands array, as a command line would be.  Please see the autodocs on &#039;&#039;&#039;ReadArgs&#039;&#039;&#039; for more information on how the template is parsed and what results are provided.&lt;br /&gt;
&lt;br /&gt;
An example of a simple function for the &amp;quot;SEND&amp;quot; command entry above could look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
STATIC VOID rexx_Send(struct ARexxCmd *ac, struct RexxMsg *rxm UNUSED)&lt;br /&gt;
{&lt;br /&gt;
	IDOS-&amp;gt;Printf(&amp;quot;   Received SEND ARexx message.\n&amp;quot;);&lt;br /&gt;
	IDOS-&amp;gt;Printf(&amp;quot;      with this text:\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// Print the text received from the message sender&lt;br /&gt;
	if (ac-&amp;gt;ac_ArgList[0])&lt;br /&gt;
		IDOS-&amp;gt;Printf(&amp;quot;      %s\n&amp;quot;, (CONST_STRPTR)ac-&amp;gt;ac_ArgList[0]);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When the command function is finished,  the contents of the three &amp;quot;result&amp;quot;  parameters are returned to the sending application.  The primary result variable &amp;quot;ac_RC&amp;quot; indicates command success and which of the other two variables are returned to the sending application.  If RC=0, then the result string &amp;quot;ac_Result&amp;quot; is sent back to the sending application.  If RC&amp;gt;0, then the secondary result variable &amp;quot;ac_RC2&amp;quot; is returned.&lt;br /&gt;
&lt;br /&gt;
==Running ARexx Script Macros==&lt;br /&gt;
&lt;br /&gt;
Besides simply sending ARexx messages between applications, ARexx provides a complete programming language that can be used to create &amp;quot;scripts&amp;quot; that an application can call and run as &amp;quot;macros&amp;quot;.  &lt;br /&gt;
&lt;br /&gt;
===Call the ARexx Script===&lt;br /&gt;
&lt;br /&gt;
To call an ARexx script from within your program, we go through the same initialization as for sending ARexx messages - create an ARexx object, define a reply hook, and then call a simple variation of the &#039;&#039;&#039;IDoMethod&#039;&#039;&#039; function.  When calling &#039;&#039;&#039;IDoMethod&#039;&#039;&#039;, instead of providing a command name and target message port name, we provide the name of the ARexx script and allow the port name field to default to the ARexx host.  When the &#039;&#039;&#039;IDoMethod&#039;&#039;&#039; is called, the ARexx host finds and runs the designated script. Here is an example of such a call:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
     IIntuition-&amp;gt;IDoMethod(arexx_obj, AM_EXECUTE, &amp;quot;rx_me_demo.rexx&amp;quot;, NULL, NULL, NULL, NULL, NULL);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
As when sending messages, all the return fields are set to NULL.  Just like sending a message, running an ARexx macro is another &amp;quot;asynchronous&amp;quot; function and any feedback will be sent back to our application using an AmigaOS &#039;&#039;&#039;signal&#039;&#039;&#039;.  And so the process of dealing with script results is the same:   the application obtains an Arexx signal mask, uses &#039;&#039;&#039;Wait&#039;&#039;&#039; function to wait for a response and calls &#039;&#039;&#039;IDoMethod&#039;&#039;&#039; with the &amp;quot;AM_HANDLEEVENT&amp;quot; method if an ARexx signal was received.  Finally, results from a called script are sent via a reply message, the reply hook is engaged and the designated reply function called.&lt;br /&gt;
&lt;br /&gt;
===Receiving Script Output===&lt;br /&gt;
&lt;br /&gt;
When the script finishes, the reply function is called and the output from the script is provided in the &amp;quot;RexxMsg&amp;quot; structure in the following arguments:&lt;br /&gt;
&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|&#039;&#039;&#039;Field Name&#039;&#039;&#039; ||&#039;&#039;&#039;Variable Type&#039;&#039;&#039; ||&#039;&#039;&#039;Usage&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|rm_Result1||uint32||This argument is the &amp;quot;primary result variable&amp;quot; and indicates success, warning, errors, etc. of calling the script.  If Result1 = 0 there was no error; 5=warning, 10=error &amp;amp; 20=severe error.&lt;br /&gt;
|-&lt;br /&gt;
|rm_Result2||uint32||This argument is either the error code or pointer to the result string from the script, depending on Result1.  If Result1=0, Result2 is a STRPTR;   if Result1&amp;gt;0, Result2 is the error number.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===The ARexx Script===&lt;br /&gt;
&lt;br /&gt;
An ARexx script called by an application can perform a vareity of functions - to interact with the user, to send commands back to the program that called it and/or to interact with other applications via ARexx messages.  As a simple scripting language, these are also things that can be added or modified by more experienced users providing a powerful way to extend the functionality of an application.&lt;br /&gt;
&lt;br /&gt;
The simplest way to send output back to the calling application is to provide a string with the ARexx &#039;&#039;&#039;return&#039;&#039;&#039; function at the end of the script.  With the primary result (&amp;quot;Result1&amp;quot;) equal to zero, the secondary result variable (&amp;quot;Result2&amp;quot;) will point to that output string.&lt;br /&gt;
&lt;br /&gt;
With a more sophisticated application, a script could send its own ARexx commands back to our application, thereby automating operations.  By default, an ARexx script run by an application is pre-configured to address the port of the application, so it&#039;s easy to send messages back to the calling application.&lt;br /&gt;
&lt;br /&gt;
==Closing Down ARexx Messaging==&lt;br /&gt;
&lt;br /&gt;
Once an application is finished and ready to close down its ARexx port, it is simply a matter of calling the &#039;&#039;&#039;DisposeObject&#039;&#039;&#039; function.  This will remove the application&#039;s ARexx port and deallocate all related resources, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
     IIntuition-&amp;gt;DisposeObject(arexx_obj);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In case there may still be ARexx messages coming in or which haven&#039;t been handled, the &amp;quot;AM_FLUSH&amp;quot; method can be used with &#039;&#039;&#039;IDoMethod&#039;&#039;&#039; to clear them out &#039;&#039;before&#039;&#039; disposing the ARexx object, like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
     IIntuition-&amp;gt;IDoMethod(arexx_obj, AM_FLUSH);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Examples =&lt;br /&gt;
&lt;br /&gt;
To download example code click [[Media:ARexxExamples.lha|on this link]].&lt;br /&gt;
&lt;br /&gt;
==EXAMPLE ONE: Sending ARexx Messages==&lt;br /&gt;
&lt;br /&gt;
The followig is a demonstration program for sending ARexx messages from an application.&lt;br /&gt;
&lt;br /&gt;
This example opens an ARexx port called &amp;quot;AREXX-SENDER&amp;quot;, asks the user for the name of a port and a text to send to that port.  It is most easily tested by addressing the &amp;quot;WORKBENCH&amp;quot; port (it&#039;s almost always there and waiting) and sending it a &amp;quot;HELP&amp;quot; message. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
************************************************************&lt;br /&gt;
**&lt;br /&gt;
** Created by:	Paul Sadlik&lt;br /&gt;
**				CodeBench 0.23 (17.09.2011)&lt;br /&gt;
**&lt;br /&gt;
** Project:		ARexx-Sender&lt;br /&gt;
**&lt;br /&gt;
** Version:		4&lt;br /&gt;
**&lt;br /&gt;
**				An exmple of how to send AN ARexx message from an AmigaOS4&lt;br /&gt;
**				C program using OS4&#039;s arexx.class.&lt;br /&gt;
**&lt;br /&gt;
** Date: 		02-01-2012 09:19:17&lt;br /&gt;
**&lt;br /&gt;
************************************************************&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;classes/arexx.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/intuition.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/arexx.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Proto for the reply hook function&lt;br /&gt;
STATIC VOID reply_callback(struct Hook *, Object *, struct RexxMsg *);&lt;br /&gt;
&lt;br /&gt;
// Declare our reply hook function static variable&lt;br /&gt;
STATIC struct Hook reply_hook;&lt;br /&gt;
&lt;br /&gt;
// Starting program&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    /*&lt;br /&gt;
     *	DECLARE VARIABLES&lt;br /&gt;
     */&lt;br /&gt;
    &lt;br /&gt;
    // Declare an Object variable for our ARexx object&lt;br /&gt;
	Object *arexx_obj;&lt;br /&gt;
	&lt;br /&gt;
	// Declare string variable to be used for the port message will be sent to&lt;br /&gt;
	char port_name[40];&lt;br /&gt;
	&lt;br /&gt;
	// Declare string variable for command to sent in ARexx message&lt;br /&gt;
	char cmd[40];&lt;br /&gt;
	&lt;br /&gt;
	// ARexx error code pointer&lt;br /&gt;
	uint32 errorCode;&lt;br /&gt;
	&lt;br /&gt;
	&lt;br /&gt;
	/*&lt;br /&gt;
	 *	INITIALIZE &amp;amp; OPEN AREXX CLASS&lt;br /&gt;
	 */&lt;br /&gt;
	&lt;br /&gt;
	// Check whether ARexx library has been opened&lt;br /&gt;
	// (opened automatically when compiled with the -lauto option)&lt;br /&gt;
	if (!ARexxBase)&lt;br /&gt;
	{&lt;br /&gt;
	    printf(&amp;quot;     ARexx not library opened\n&amp;quot;);&lt;br /&gt;
		return RETURN_FAIL;&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;     ARexx library opened\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// open ARexx class object (creates port) - see autodocs ATTRIBUTES list&lt;br /&gt;
	arexx_obj = IIntuition-&amp;gt;NewObject(NULL, &amp;quot;arexx.class&amp;quot;,&lt;br /&gt;
		AREXX_HostName, &amp;quot;AREXX-SENDER&amp;quot;,		// you must set an ARexx port name for this app&lt;br /&gt;
		AREXX_NoSlot, TRUE,					// set whether name should be incremented&lt;br /&gt;
		AREXX_ErrorCode, &amp;amp;errorCode,		// set variable to receive error code, if any&lt;br /&gt;
		AREXX_ReplyHook, &amp;amp;reply_hook,		// the hook structure defines how replies will be handled&lt;br /&gt;
	TAG_DONE);&lt;br /&gt;
	&lt;br /&gt;
	// if ARexx class was successfuly opened, continue &lt;br /&gt;
	if (arexx_obj)&lt;br /&gt;
	{&lt;br /&gt;
		// Define ReplyTo hook structure - to set which function gets called when a reply is received&lt;br /&gt;
		printf(&amp;quot;     set up ReplyTo hook\n&amp;quot;);&lt;br /&gt;
		reply_hook.h_Entry    = (HOOKFUNC)reply_callback;	// pointer to function name to be called&lt;br /&gt;
		reply_hook.h_SubEntry = NULL;&lt;br /&gt;
		reply_hook.h_Data     = NULL;&lt;br /&gt;
		&lt;br /&gt;
		/*&lt;br /&gt;
		 *	GET INPUT FROM USER&lt;br /&gt;
		 */&lt;br /&gt;
		&lt;br /&gt;
		// Ask user for name of port to send message to&lt;br /&gt;
		printf(&amp;quot;Please enter the UPPERCASE name of an ARexx port to send a message to.\n&amp;quot;);&lt;br /&gt;
		fgets(port_name,sizeof(port_name),stdin);&lt;br /&gt;
		port_name[strlen(port_name)-1] = &#039;\0&#039;;		// strip \n off end of string&lt;br /&gt;
		printf(&amp;quot;     Got ARexx port name =&amp;gt;%s&amp;lt;\n&amp;quot;,port_name);&lt;br /&gt;
		&lt;br /&gt;
		// Ask user for message to send - some command the host will accept&lt;br /&gt;
		printf(&amp;quot;Please enter a message to send.\n&amp;quot;);&lt;br /&gt;
		fgets(cmd,sizeof(cmd),stdin);&lt;br /&gt;
		cmd[strlen(cmd)-1] = &#039;\0&#039;;		// strip \n off end of string&lt;br /&gt;
		printf(&amp;quot;     Got ARexx message =&amp;gt;%s&amp;lt;\n&amp;quot;,cmd);&lt;br /&gt;
		&lt;br /&gt;
		/*&lt;br /&gt;
		 *	SEND AREXX MESSAGE&lt;br /&gt;
		 */&lt;br /&gt;
		&lt;br /&gt;
		// check whether target message port is found&lt;br /&gt;
		// (FindPort must be enclosed in a Forbid/Permit pair)&lt;br /&gt;
		IExec-&amp;gt;Forbid();&lt;br /&gt;
		if (IExec-&amp;gt;FindPort(port_name))&lt;br /&gt;
		{&lt;br /&gt;
			// target message port found, send message&lt;br /&gt;
			IExec-&amp;gt;Permit();&lt;br /&gt;
			printf(&amp;quot;     sending ARexx message\n&amp;quot;);&lt;br /&gt;
			IIntuition-&amp;gt;IDoMethod(arexx_obj, AM_EXECUTE,cmd,port_name, NULL, NULL, NULL, NULL);&lt;br /&gt;
			printf(&amp;quot;     ARexx message sent, waiting for reply\n&amp;quot;);&lt;br /&gt;
		&lt;br /&gt;
			/*&lt;br /&gt;
			 *	WAIT FOR HOST TO REPLY TO MESSAGE&lt;br /&gt;
			 */&lt;br /&gt;
			&lt;br /&gt;
			// Obtain wait mask for arexx class&lt;br /&gt;
			ULONG rxsig = 0, signal;&lt;br /&gt;
			IIntuition-&amp;gt;GetAttr(AREXX_SigMask, arexx_obj, &amp;amp;rxsig);&lt;br /&gt;
			&lt;br /&gt;
			// Call Wait command to wait for reply to our sent message&lt;br /&gt;
			signal = IExec-&amp;gt;Wait(rxsig | SIGBREAKF_CTRL_C);&lt;br /&gt;
			printf(&amp;quot;     Program received some message...\n&amp;quot;);&lt;br /&gt;
			&lt;br /&gt;
			/*&lt;br /&gt;
			 *	HANDLE RESPONSE&lt;br /&gt;
			 */&lt;br /&gt;
			&lt;br /&gt;
			// Did we receive an ARexx event ?&lt;br /&gt;
			if (signal &amp;amp; rxsig)&lt;br /&gt;
			{&lt;br /&gt;
				printf(&amp;quot;     ARexx message received... handling...\n&amp;quot;);&lt;br /&gt;
				&lt;br /&gt;
				// Handling the incoming event will cause the reply_hook function to get called&lt;br /&gt;
				IIntuition-&amp;gt;IDoMethod(arexx_obj, AM_HANDLEEVENT);&lt;br /&gt;
				printf(&amp;quot;     ARexx message handled!\n&amp;quot;);&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			// Did the user pressed Control-C ?&lt;br /&gt;
			if (signal &amp;amp; SIGBREAKF_CTRL_C)&lt;br /&gt;
			{&lt;br /&gt;
				printf(&amp;quot;     Received CTRL-C message.\n&amp;quot;);&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		else&lt;br /&gt;
		{&lt;br /&gt;
		    // target message port not found&lt;br /&gt;
		    IExec-&amp;gt;Permit();&lt;br /&gt;
			printf(&amp;quot;     Unable to send ARexx message, port name not found..\n&amp;quot;);&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		/*&lt;br /&gt;
		 *	DISPOSE OF AREXX CLASS OBJECT&lt;br /&gt;
		 */&lt;br /&gt;
		printf(&amp;quot;     Disposing of ARexx object.\n&amp;quot;);&lt;br /&gt;
		IIntuition-&amp;gt;DisposeObject(arexx_obj);&lt;br /&gt;
		&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		IDOS-&amp;gt;Printf(&amp;quot;     Could not create the ARexx object.\n&amp;quot;);&lt;br /&gt;
		if (errorCode == RXERR_PORT_ALREADY_EXISTS)&lt;br /&gt;
			IDOS-&amp;gt;Printf(&amp;quot;          Port already exists.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;     Quitting...   GOODBYE!.\n&amp;quot;);&lt;br /&gt;
	return RETURN_OK;	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*	reply_callback FUNCTION&lt;br /&gt;
 *&lt;br /&gt;
 *	This function gets called whenever we get an ARexx reply and then call the &amp;quot;AM_HANDLEEVENT&amp;quot;&lt;br /&gt;
 *	arexx class method.  In this example, we will see a reply come back from the REXX host when&lt;br /&gt;
 *	it has finished with the command we sent.&lt;br /&gt;
 */&lt;br /&gt;
STATIC VOID reply_callback(struct Hook *hook UNUSED, Object *o UNUSED, struct RexxMsg *rxm)&lt;br /&gt;
{&lt;br /&gt;
	printf(&amp;quot;     HOOK FUNCTION RUNNING...\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	/*&lt;br /&gt;
	 *	DISPLAY CONTENTS OF REPLY MESSAGE&lt;br /&gt;
	 */&lt;br /&gt;
	&lt;br /&gt;
	// Show primary result code (integer) - 0 = success, no error&lt;br /&gt;
	printf(&amp;quot;          Result1 =&amp;gt;%ld&amp;lt;\n&amp;quot;,rxm-&amp;gt;rm_Result1);&lt;br /&gt;
	&lt;br /&gt;
	// display secondary result - succesful or an error code&lt;br /&gt;
	if (rxm-&amp;gt;rm_Result1 == 0)&lt;br /&gt;
		&lt;br /&gt;
		// if result code is 0, display any result string sent back&lt;br /&gt;
		printf(&amp;quot;          Result2 =&amp;gt;%s&amp;lt;\n&amp;quot;,(STRPTR)rxm-&amp;gt;rm_Result2);&lt;br /&gt;
		&lt;br /&gt;
	else&lt;br /&gt;
		&lt;br /&gt;
		// if result code &amp;gt; 0, display error code number&lt;br /&gt;
		printf(&amp;quot;          Result2 =&amp;gt;%ld&amp;lt;\n&amp;quot;,rxm-&amp;gt;rm_Result2);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==EXAMPLE TWO: Receiving ARexx Command Messages==&lt;br /&gt;
&lt;br /&gt;
The following is a demonstration of an application that can receive a number of ARexx command messages.&lt;br /&gt;
&lt;br /&gt;
This program first declares a &amp;quot;Commands&amp;quot; array that spells out what ARexx commands it will receive, how they are formatted and what functions to call.  The program next goes through the typical steps of initializing ARexx and opening an ARexx port called &amp;quot;AREXX-RECEIVER&amp;quot;.  Then it enters a loop - waiting for incoming messages until it receives a &amp;quot;QUIT&amp;quot; command.  Finally, there are functions for each command that the application accepts.&lt;br /&gt;
&lt;br /&gt;
The program from Example One can be used to send commands to this program.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
************************************************************&lt;br /&gt;
**&lt;br /&gt;
** Created by:	Paul Sadlik&lt;br /&gt;
**				CodeBench 0.23 (17.09.2011)&lt;br /&gt;
**&lt;br /&gt;
** Project:		ARexx-Receiver&lt;br /&gt;
**&lt;br /&gt;
** Version:		4&lt;br /&gt;
**&lt;br /&gt;
**				An example of how to receive ARexx messages with an AmigaOS4&lt;br /&gt;
**				C program using OS4&#039;s arexx.class.&lt;br /&gt;
**&lt;br /&gt;
** Date:		27-11-2011&lt;br /&gt;
**&lt;br /&gt;
** Version:		v2&lt;br /&gt;
**&lt;br /&gt;
************************************************************&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;classes/arexx.h&amp;gt;&lt;br /&gt;
#include &amp;lt;utility/utility.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/intuition.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/utility.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/arexx.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Protos for the ARexx command functions to be called when our commands are received&lt;br /&gt;
STATIC VOID rexx_Name (struct ARexxCmd *, struct RexxMsg *);&lt;br /&gt;
STATIC VOID rexx_Version(struct ARexxCmd *, struct RexxMsg *);&lt;br /&gt;
STATIC VOID rexx_Quit (struct ARexxCmd *, struct RexxMsg *);&lt;br /&gt;
STATIC VOID rexx_Send (struct ARexxCmd *, struct RexxMsg *);&lt;br /&gt;
STATIC VOID rexx_Date (struct ARexxCmd *, struct RexxMsg *);&lt;br /&gt;
STATIC VOID rexx_Help (struct ARexxCmd *, struct RexxMsg *);&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 *	DECLARE COMMANDS RECOGNIZED BT THIS AREXX HOST&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
const uint8 NoOfCmds = 6;&lt;br /&gt;
//uint8 NoOfCmds;&lt;br /&gt;
&lt;br /&gt;
// Declare the array of structure that defines all the functions, parameters, etc.&lt;br /&gt;
// of the commands that are valid for this program.  (This array must neve&lt;br /&gt;
// be const because arexx.class writes into it).  See the &amp;quot;AREXX_Commands&amp;quot;&lt;br /&gt;
// description in arexx_cl autodocs.&lt;br /&gt;
STATIC struct ARexxCmd Commands[] =&lt;br /&gt;
{&lt;br /&gt;
	{&amp;quot;NAME&amp;quot;,    0, rexx_Name,    NULL,       0, NULL, 0, 0, NULL},&lt;br /&gt;
	{&amp;quot;VERSION&amp;quot;, 1, rexx_Version, NULL,       0, NULL, 0, 0, NULL},&lt;br /&gt;
	{&amp;quot;QUIT&amp;quot;,    2, rexx_Quit,    NULL,       0, NULL, 0, 0, NULL},&lt;br /&gt;
	{&amp;quot;SEND&amp;quot;,    3, rexx_Send,    &amp;quot;TEXT/F&amp;quot;,   0, NULL, 0, 0, NULL},&lt;br /&gt;
	{&amp;quot;DATE&amp;quot;,    4, rexx_Date,    &amp;quot;SYSTEM/S&amp;quot;, 0, NULL, 0, 0, NULL},&lt;br /&gt;
	{&amp;quot;HELP&amp;quot;,    5, rexx_Help,    NULL,       0, NULL, 0, 0, NULL}&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
//	declare string buffer pointer to be used for creating HELP msg response&lt;br /&gt;
STRPTR buffer = NULL;&lt;br /&gt;
&lt;br /&gt;
// Declare/define a global variable that we&#039;re running&lt;br /&gt;
BOOL running = TRUE;&lt;br /&gt;
&lt;br /&gt;
// ARexx error code pointer&lt;br /&gt;
	uint32 errorCode;&lt;br /&gt;
&lt;br /&gt;
// Starting program&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	// Declare an Object variable for our ARexx object&lt;br /&gt;
	Object *arexx_obj;&lt;br /&gt;
	&lt;br /&gt;
	/*&lt;br /&gt;
	 *	INITIALIZE &amp;amp; OPEN AREXX CLASS&lt;br /&gt;
	 */&lt;br /&gt;
	&lt;br /&gt;
	// Check whether ARexx library has been opened&lt;br /&gt;
	//    (opened automatically when compiled with the -lauto option)&lt;br /&gt;
	if (!ARexxBase)&lt;br /&gt;
	{&lt;br /&gt;
	    printf(&amp;quot;     ARexx not library opened\n&amp;quot;);&lt;br /&gt;
		return RETURN_FAIL;&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;ARexx library opened\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// open ARexx class object (creates port) - see autodocs ATTRIBUTES list&lt;br /&gt;
	arexx_obj = IIntuition-&amp;gt;NewObject(NULL, &amp;quot;arexx.class&amp;quot;,&lt;br /&gt;
		AREXX_HostName, &amp;quot;AREXX-RECEIVER&amp;quot;,		// set an ARexx port name for this app&lt;br /&gt;
		AREXX_NoSlot, TRUE,					// set whether name should be incremented&lt;br /&gt;
		AREXX_ErrorCode, &amp;amp;errorCode,		// set variable to receive error code, if any&lt;br /&gt;
		AREXX_Commands, Commands,				// provide structure of commands recognized by app&lt;br /&gt;
		AREXX_NoSlot, TRUE,						// set to not number port name (there can only be one)&lt;br /&gt;
	TAG_DONE);&lt;br /&gt;
	&lt;br /&gt;
	// if ARexx class was successfuly opened, continue &lt;br /&gt;
	if (arexx_obj)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;ARexx port opened\n&amp;quot;);&lt;br /&gt;
		&lt;br /&gt;
		// Determine the number of commands&lt;br /&gt;
		//NoOfCmds = (sizeof(Commands)/sizeof(ARexxCmd)) -1;&lt;br /&gt;
		&lt;br /&gt;
		// Obtain wait mask for arexx class&lt;br /&gt;
		ULONG rxsig = 0, signal;&lt;br /&gt;
		IIntuition-&amp;gt;GetAttr(AREXX_SigMask, arexx_obj, &amp;amp;rxsig);&lt;br /&gt;
		&lt;br /&gt;
		/*&lt;br /&gt;
		 *	START EVENT LOOP&lt;br /&gt;
		 */&lt;br /&gt;
		&lt;br /&gt;
		// continue loop until &amp;quot;running&amp;quot; variable is FALSE&lt;br /&gt;
		do&lt;br /&gt;
		{&lt;br /&gt;
			// Wait for incoming messages from Intution&lt;br /&gt;
			signal = IExec-&amp;gt;Wait(rxsig | SIGBREAKF_CTRL_C);&lt;br /&gt;
			printf(&amp;quot;Program received some message...\n&amp;quot;);&lt;br /&gt;
			&lt;br /&gt;
			// Did we receive an ARexx event ?&lt;br /&gt;
			if (signal &amp;amp; rxsig)&lt;br /&gt;
			{&lt;br /&gt;
			    /*&lt;br /&gt;
				 *	HANDLE INCOMING MESSAGE&lt;br /&gt;
				 */&lt;br /&gt;
				printf(&amp;quot;ARexx message received... handling...\n&amp;quot;);&lt;br /&gt;
				&lt;br /&gt;
				// &amp;quot;Handling&amp;quot; the incoming event will cause command functions to get&lt;br /&gt;
				// called as defined in the &amp;quot;Commands&amp;quot; structure above.&lt;br /&gt;
				IIntuition-&amp;gt;IDoMethod(arexx_obj, AM_HANDLEEVENT);&lt;br /&gt;
				printf(&amp;quot;ARexx message handled!\n&amp;quot;);&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			// Did the user pressed Control-C (a.k.a., &amp;quot;Break&amp;quot;) ?&lt;br /&gt;
			if (signal &amp;amp; SIGBREAKF_CTRL_C)&lt;br /&gt;
			{&lt;br /&gt;
				printf(&amp;quot;Received CTRL-C message.\n&amp;quot;);&lt;br /&gt;
				&lt;br /&gt;
				// set &amp;quot;running&amp;quot; to quit event loop&lt;br /&gt;
				running = FALSE;&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		while (running);&lt;br /&gt;
		&lt;br /&gt;
		/*&lt;br /&gt;
		 *	CLEAR OUT ANY AREXX MESSAGES&lt;br /&gt;
		 */&lt;br /&gt;
		IIntuition-&amp;gt;IDoMethod(arexx_obj, AM_FLUSH);&lt;br /&gt;
		&lt;br /&gt;
		/*&lt;br /&gt;
		 *	DISPOSE OF AREXX CLASS OBJECT&lt;br /&gt;
		 */&lt;br /&gt;
		printf(&amp;quot;Disposing of ARexx port.\n&amp;quot;);&lt;br /&gt;
		IIntuition-&amp;gt;DisposeObject(arexx_obj);&lt;br /&gt;
		&lt;br /&gt;
		// free any memory used by HELP response string buffer&lt;br /&gt;
		if (buffer)			&lt;br /&gt;
			IExec-&amp;gt;FreeVec(buffer);&lt;br /&gt;
			&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		IDOS-&amp;gt;Printf(&amp;quot;     Could not create the ARexx object.\n&amp;quot;);&lt;br /&gt;
		if (errorCode == RXERR_PORT_ALREADY_EXISTS)&lt;br /&gt;
			IDOS-&amp;gt;Printf(&amp;quot;          Port already exists.\n&amp;quot;);&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	printf(&amp;quot;Quitting...   GOODBYE!.\n&amp;quot;);&lt;br /&gt;
	return RETURN_OK;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 *	rexx_Name FUNCTION&lt;br /&gt;
 *&lt;br /&gt;
 *	This function gets called when the &amp;quot;NAME&amp;quot; command is received and the&lt;br /&gt;
 *	&amp;quot;AM_HANDLEEVENT&amp;quot; arexx class method called.&lt;br /&gt;
 *&lt;br /&gt;
 *	This function simply returns this program&#039;s name.&lt;br /&gt;
 */&lt;br /&gt;
STATIC VOID rexx_Name(struct ARexxCmd *ac, struct RexxMsg *rxm UNUSED)&lt;br /&gt;
{&lt;br /&gt;
	printf(&amp;quot;   Received NAME ARexx message.\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// return the program name to the message sender&lt;br /&gt;
	ac-&amp;gt;ac_Result = (STRPTR) &amp;quot;ARexxReceiver&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 *	rexx_Version FUNCTION&lt;br /&gt;
 *&lt;br /&gt;
 *	This function gets called when the &amp;quot;VERSION&amp;quot; command is received and the&lt;br /&gt;
 *	&amp;quot;AM_HANDLEEVENT&amp;quot; arexx class method called.&lt;br /&gt;
 *&lt;br /&gt;
 *	This function simply returns this program&#039;s version number.&lt;br /&gt;
 */&lt;br /&gt;
STATIC VOID rexx_Version(struct ARexxCmd *ac, struct RexxMsg *rxm UNUSED)&lt;br /&gt;
{&lt;br /&gt;
	printf(&amp;quot;   Received VERSION ARexx message.\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// return the program version to the message sender&lt;br /&gt;
	ac-&amp;gt;ac_Result = (STRPTR) &amp;quot;4.0&amp;quot;;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 *	rexx_Quit FUNCTION&lt;br /&gt;
 *&lt;br /&gt;
 *	This function gets called when the &amp;quot;QUIT&amp;quot; command is received and the&lt;br /&gt;
 *	&amp;quot;AM_HANDLEEVENT&amp;quot; arexx class method called.&lt;br /&gt;
 *&lt;br /&gt;
 *	This function will cause this program to exit its event loop and quit.&lt;br /&gt;
 */&lt;br /&gt;
STATIC VOID rexx_Quit(struct ARexxCmd *ac, struct RexxMsg *rxm UNUSED)&lt;br /&gt;
{&lt;br /&gt;
	printf(&amp;quot;   Received QUIT message.\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// Respond that this app is quitting&lt;br /&gt;
	ac-&amp;gt;ac_Result = (STRPTR) &amp;quot;ARexxReceiver quitting...&amp;quot;;&lt;br /&gt;
	&lt;br /&gt;
	// Set &amp;quot;running&amp;quot; to quit the main event loop&lt;br /&gt;
	running = FALSE;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 *	rexx_Send FUNCTION&lt;br /&gt;
 *&lt;br /&gt;
 *	This function gets called when the &amp;quot;SEND&amp;quot; command is received (with text&lt;br /&gt;
 *	to be printed) and the &amp;quot;AM_HANDLEEVENT&amp;quot; arexx class method called.&lt;br /&gt;
 *&lt;br /&gt;
 *	This function will print the received text to the console.&lt;br /&gt;
 */&lt;br /&gt;
STATIC VOID rexx_Send(struct ARexxCmd *ac, struct RexxMsg *rxm UNUSED)&lt;br /&gt;
{&lt;br /&gt;
	printf(&amp;quot;   Received SEND ARexx message.\n&amp;quot;);&lt;br /&gt;
	printf(&amp;quot;      with this text:\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// Print the text received from the message sender&lt;br /&gt;
	if (ac-&amp;gt;ac_ArgList[0])&lt;br /&gt;
		printf(&amp;quot;      %s\n&amp;quot;, (STRPTR)ac-&amp;gt;ac_ArgList[0]);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 *	rexx_Date FUNCTION&lt;br /&gt;
 *&lt;br /&gt;
 *	This function gets called when the &amp;quot;DATE&amp;quot; command is received and the&lt;br /&gt;
 *	&amp;quot;AM_HANDLEEVENT&amp;quot; arexx class method called.&lt;br /&gt;
 *&lt;br /&gt;
 *	Without any parameters this command will get a response of this program&#039;s&lt;br /&gt;
 *	compilation date.  With the &amp;quot;SYSTEM&amp;quot; parameter, the response will be the&lt;br /&gt;
 *	current system date.&lt;br /&gt;
 */&lt;br /&gt;
STATIC VOID rexx_Date(struct ARexxCmd *ac, struct RexxMsg *rxm UNUSED)&lt;br /&gt;
{&lt;br /&gt;
	printf(&amp;quot;   Received DATE ARexx message.\n&amp;quot;);&lt;br /&gt;
	// is the SYSTEM switch specified with the received command message?&lt;br /&gt;
	&lt;br /&gt;
	if (!ac-&amp;gt;ac_ArgList[0])&lt;br /&gt;
	{&lt;br /&gt;
		// return the compilation date.&lt;br /&gt;
		printf(&amp;quot;      with no parameters - returning compile date.\n&amp;quot;);&lt;br /&gt;
		ac-&amp;gt;ac_Result = (STRPTR) &amp;quot;1-21-12&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		// compute system date and store in systemDate buffer&lt;br /&gt;
		printf(&amp;quot;      with SYSTEM parameter - returning system date.\n&amp;quot;);&lt;br /&gt;
		&lt;br /&gt;
		// declare the needed variables&lt;br /&gt;
		STATIC TEXT systemDate[LEN_DATSTRING];&lt;br /&gt;
		struct DateTime dt;&lt;br /&gt;
		&lt;br /&gt;
		// get the system date&lt;br /&gt;
		IDOS-&amp;gt;DateStamp(&amp;amp;dt.dat_Stamp);&lt;br /&gt;
		&lt;br /&gt;
		// set datetime struct to format output&lt;br /&gt;
		dt.dat_Format  = FORMAT_USA;&lt;br /&gt;
		dt.dat_Flags   = 0;&lt;br /&gt;
		dt.dat_StrDay  = NULL;&lt;br /&gt;
		dt.dat_StrDate = systemDate;&lt;br /&gt;
		dt.dat_StrTime = NULL;&lt;br /&gt;
		&lt;br /&gt;
		// get string with date&lt;br /&gt;
		IDOS-&amp;gt;DateToStr(&amp;amp;dt);&lt;br /&gt;
&lt;br /&gt;
		// return string with system date&lt;br /&gt;
		ac-&amp;gt;ac_Result = systemDate;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 *	rexx_Help FUNCTION&lt;br /&gt;
 *&lt;br /&gt;
 *	This function gets called when the &amp;quot;HELP&amp;quot; command is received and the&lt;br /&gt;
 *	&amp;quot;AM_HANDLEEVENT&amp;quot; arexx class method called.&lt;br /&gt;
 *&lt;br /&gt;
 *	This function will build a list of all the commands this program is&lt;br /&gt;
 *	defined to handle and will return a comma separated list to the message&lt;br /&gt;
 *	sender. &lt;br /&gt;
 */&lt;br /&gt;
STATIC VOID rexx_Help(struct ARexxCmd *ac, struct RexxMsg *rxm UNUSED)&lt;br /&gt;
{&lt;br /&gt;
	uint16 cmd_no = 0;&lt;br /&gt;
	printf(&amp;quot;   Received HELP ARexx message.\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	// loop though the commands array, accumulating commands list&lt;br /&gt;
	for(cmd_no = 0; cmd_no &amp;lt; NoOfCmds; ++cmd_no)&lt;br /&gt;
	{&lt;br /&gt;
		if (cmd_no == 0)&lt;br /&gt;
		{&lt;br /&gt;
			// try to add command name to empty string buffer&lt;br /&gt;
			buffer = IUtility-&amp;gt;ASPrintf(&amp;quot;%s&amp;quot;,Commands[cmd_no].ac_Name);&lt;br /&gt;
			if (buffer==NULL)&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
		else&lt;br /&gt;
		{&lt;br /&gt;
			// try to add command name to accumulating string buffer&lt;br /&gt;
			buffer = IUtility-&amp;gt;ASPrintf(&amp;quot;%s, %s&amp;quot;,buffer,Commands[cmd_no].ac_Name);&lt;br /&gt;
			if (buffer==NULL)&lt;br /&gt;
				break;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	//done looping through commands - do we have a list?&lt;br /&gt;
	if (buffer==NULL)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;      unable to build commands list.\n&amp;quot;);&lt;br /&gt;
		// return list of accepted commands to ARexx message sender&lt;br /&gt;
		ac-&amp;gt;ac_Result = (STRPTR) &amp;quot;Unable to build commands list&amp;quot;;&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;      command list = &amp;gt;%s&amp;lt;\n&amp;quot;,buffer);&lt;br /&gt;
		// return list of accepted commands to ARexx message sender&lt;br /&gt;
		ac-&amp;gt;ac_Result = buffer;&lt;br /&gt;
		&lt;br /&gt;
		// NOTE: memory allocated for buffer will be freed at end of main func&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==EXAMPLE THREE: Calling ARexx Scripts==&lt;br /&gt;
&lt;br /&gt;
This application and ARexx script demonstrate a simple case where an application can run an ARexx script and receive results from it.&lt;br /&gt;
&lt;br /&gt;
===The Application===&lt;br /&gt;
&lt;br /&gt;
This program follows the pattern of Example One above except that it causes an ARexx script to be run instead of sending an ARexx message.  Like Example one, it waits for a response and ARexx results are handled by a reply function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
************************************************************&lt;br /&gt;
**&lt;br /&gt;
** Created by:	Paul Sadlik&lt;br /&gt;
**				CodeBench 0.23 (17.09.2011)&lt;br /&gt;
**&lt;br /&gt;
** Project:		ARexx-Macro&lt;br /&gt;
**&lt;br /&gt;
** Version:		2&lt;br /&gt;
**&lt;br /&gt;
**				An exmple of how to call an ARexx macro script from an&lt;br /&gt;
**				AmigaOS4 C program using OS4&#039;s arexx.class.&lt;br /&gt;
**&lt;br /&gt;
** Date:		27-11-2011&lt;br /&gt;
**&lt;br /&gt;
************************************************************&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
#include &amp;lt;classes/arexx.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;proto/exec.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/intuition.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/dos.h&amp;gt;&lt;br /&gt;
#include &amp;lt;proto/arexx.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Proto for the reply hook function.&lt;br /&gt;
STATIC VOID reply_callback(struct Hook *, Object *, struct RexxMsg *);&lt;br /&gt;
&lt;br /&gt;
// Declare our reply hook function static variable&lt;br /&gt;
STATIC struct Hook reply_hook;&lt;br /&gt;
&lt;br /&gt;
// Starting program&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
	/*&lt;br /&gt;
     *	DECLARE VARIABLES&lt;br /&gt;
     */&lt;br /&gt;
    &lt;br /&gt;
    // Declare an Object variable for our ARexx object&lt;br /&gt;
	Object *arexx_obj;&lt;br /&gt;
	&lt;br /&gt;
	/*&lt;br /&gt;
	 *	INITIALIZE &amp;amp; OPEN AREXX CLASS&lt;br /&gt;
	 */&lt;br /&gt;
	&lt;br /&gt;
	// Check whether ARexx library has been opened&lt;br /&gt;
	// (opened automatically when compiled with the -lauto option)&lt;br /&gt;
	if (!ARexxBase)&lt;br /&gt;
	{&lt;br /&gt;
		printf(&amp;quot;     ARexx not library opened\n&amp;quot;);&lt;br /&gt;
		return RETURN_FAIL;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// open ARexx class object (creates port) - see autodocs ATTRIBUTES list&lt;br /&gt;
	arexx_obj = IIntuition-&amp;gt;NewObject(NULL, &amp;quot;arexx.class&amp;quot;,&lt;br /&gt;
		AREXX_HostName, &amp;quot;AREXX-MACRO&amp;quot;,		// you must set ARexx port name for this app&lt;br /&gt;
//		AREXX_Commands, NULL,&lt;br /&gt;
		AREXX_NoSlot, TRUE,					// set it so the port name is not enumerated&lt;br /&gt;
		AREXX_ReplyHook, &amp;amp;reply_hook,		// the hook structure defines how replies will be handled&lt;br /&gt;
	TAG_DONE);&lt;br /&gt;
&lt;br /&gt;
	// if ARexx class was successfuly opened, continue &lt;br /&gt;
	if (arexx_obj)&lt;br /&gt;
	{&lt;br /&gt;
		// Define ReplyTo hook structure - what function gets called when a reply is received&lt;br /&gt;
		reply_hook.h_Entry    = (HOOKFUNC)reply_callback;	// pointer to function name to be called&lt;br /&gt;
		reply_hook.h_SubEntry = NULL;&lt;br /&gt;
		reply_hook.h_Data     = NULL;&lt;br /&gt;
		&lt;br /&gt;
		/*&lt;br /&gt;
		 *	RUN AREXX SCRIPT MACRO&lt;br /&gt;
		 */&lt;br /&gt;
		&lt;br /&gt;
		printf(&amp;quot;Calling ARexx macro script...\n&amp;quot;);&lt;br /&gt;
		// Run ARexx script in current directory (or REXX: path).&lt;br /&gt;
		// Results will be returned to the &amp;quot;reply_callback&amp;quot; function.&lt;br /&gt;
		IIntuition-&amp;gt;IDoMethod(arexx_obj, AM_EXECUTE, &amp;quot;rx_me_demo.rexx&amp;quot;, NULL, NULL, NULL, NULL, NULL);&lt;br /&gt;
		printf(&amp;quot;Calling macro done.\n&amp;quot;);&lt;br /&gt;
		&lt;br /&gt;
		/*&lt;br /&gt;
		 *	WAIT FOR RESPONSE&lt;br /&gt;
		 */&lt;br /&gt;
		&lt;br /&gt;
		// Obtain wait mask for arexx class&lt;br /&gt;
		ULONG rxsig = 0, signal;&lt;br /&gt;
		IIntuition-&amp;gt;GetAttr(AREXX_SigMask, arexx_obj, &amp;amp;rxsig);&lt;br /&gt;
		&lt;br /&gt;
		// Wait for incoming messages from Intution&lt;br /&gt;
		signal = IExec-&amp;gt;Wait(rxsig | SIGBREAKF_CTRL_C);&lt;br /&gt;
		printf(&amp;quot;Program received some message...\n&amp;quot;);&lt;br /&gt;
		&lt;br /&gt;
		// Did we receive an ARexx event ?&lt;br /&gt;
		if (signal &amp;amp; rxsig)&lt;br /&gt;
			{&lt;br /&gt;
				printf(&amp;quot;ARexx message received...\n&amp;quot;);&lt;br /&gt;
				&lt;br /&gt;
				// &amp;quot;Handling&amp;quot; the incoming event will cause the reply_hook function to get called&lt;br /&gt;
				IIntuition-&amp;gt;IDoMethod(arexx_obj, AM_HANDLEEVENT);&lt;br /&gt;
				printf(&amp;quot;ARexx message handled!\n&amp;quot;);&lt;br /&gt;
			}&lt;br /&gt;
		&lt;br /&gt;
		// Did the user enter a Control-C (a.k.a., &amp;quot;Break&amp;quot;) ?&lt;br /&gt;
		if (signal &amp;amp; SIGBREAKF_CTRL_C)&lt;br /&gt;
			{&lt;br /&gt;
				printf(&amp;quot;Received CTRL-C message.\n&amp;quot;);&lt;br /&gt;
			}&lt;br /&gt;
		&lt;br /&gt;
		/*&lt;br /&gt;
		 *	DISPOSE OF AREXX CLASS OBJECT&lt;br /&gt;
		 */&lt;br /&gt;
		printf(&amp;quot;Disposing of ARexx port.\n&amp;quot;);&lt;br /&gt;
		IIntuition-&amp;gt;DisposeObject(arexx_obj);&lt;br /&gt;
	}&lt;br /&gt;
	else&lt;br /&gt;
		IDOS-&amp;gt;Printf(&amp;quot;Could not create the ARexx host.\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	printf(&amp;quot;Quitting...   GOODBYE!.\n&amp;quot;);&lt;br /&gt;
	return RETURN_OK;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*	reply_callback FUNCTION&lt;br /&gt;
 *&lt;br /&gt;
 *	This function gets called whenever we get an ARexx reply and then call the &amp;quot;AM_HANDLEEVENT&amp;quot;&lt;br /&gt;
 *	arexx class method.  In this example, we will see a reply come back from the REXX host when&lt;br /&gt;
 *	it has finished with the command we sent.&lt;br /&gt;
 */&lt;br /&gt;
STATIC VOID reply_callback(struct Hook *hook UNUSED, Object *o UNUSED, struct RexxMsg *rxm)&lt;br /&gt;
{&lt;br /&gt;
	printf(&amp;quot;     HOOK FUNCTION RUNNING...\n&amp;quot;);&lt;br /&gt;
	&lt;br /&gt;
	/*&lt;br /&gt;
	 *	DISPLAY CONTENTS OF REPLY MESSAGE&lt;br /&gt;
	 */&lt;br /&gt;
	&lt;br /&gt;
	// Show primary result code (integer) - 0 = success, no error&lt;br /&gt;
	printf(&amp;quot;          Result1 =&amp;gt;%ld&amp;lt;\n&amp;quot;,rxm-&amp;gt;rm_Result1);&lt;br /&gt;
	&lt;br /&gt;
	// display secondary result - succesful or an error code&lt;br /&gt;
	if (rxm-&amp;gt;rm_Result1 == 0)&lt;br /&gt;
		&lt;br /&gt;
		// if result code is 0, display any result string sent back&lt;br /&gt;
		printf(&amp;quot;          Result2 =&amp;gt;%s&amp;lt;\n&amp;quot;,(STRPTR)rxm-&amp;gt;rm_Result2);&lt;br /&gt;
		&lt;br /&gt;
	else&lt;br /&gt;
		&lt;br /&gt;
		// if result code &amp;gt; 0, display error code number&lt;br /&gt;
		printf(&amp;quot;          Result2 =&amp;gt;%ld&amp;lt;\n&amp;quot;,rxm-&amp;gt;rm_Result2);&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===The Script===&lt;br /&gt;
&lt;br /&gt;
This is a simple ARexx script that addresses the AmigaOS command line (&amp;quot;COMMAND&amp;quot;), it uses &amp;quot;RequestString&amp;quot; to get a string from the user and then it sends that input back to the calling application with the &amp;quot;Return&amp;quot; function.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* Small macro script for the small arexxclass demo */&lt;br /&gt;
&lt;br /&gt;
options results&lt;br /&gt;
&lt;br /&gt;
address COMMAND&lt;br /&gt;
&lt;br /&gt;
cmdline = &#039;c:requeststring &amp;gt;t:DemoInput &amp;quot;Sample Macro Script&amp;quot; &amp;quot;This is the macro script running!*N*NPlease enter a response message*Nto send back to your app...&amp;quot;&#039;&lt;br /&gt;
&lt;br /&gt;
(cmdline)&lt;br /&gt;
&lt;br /&gt;
if open(handle,&amp;quot;t:DemoInput&amp;quot;,&#039;r&#039;) then do&lt;br /&gt;
	input = readln(handle)&lt;br /&gt;
	call close(handle)&lt;br /&gt;
	address command &#039;c:delete T:DemoInput&#039;&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
return input&lt;br /&gt;
&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>James Jacobs</name></author>
	</entry>
	<entry>
		<id>https://wiki.amigaos.net/w/index.php?title=Talk:BOOPSI_Popup_Menus_-_Part_1&amp;diff=2503</id>
		<title>Talk:BOOPSI Popup Menus - Part 1</title>
		<link rel="alternate" type="text/html" href="https://wiki.amigaos.net/w/index.php?title=Talk:BOOPSI_Popup_Menus_-_Part_1&amp;diff=2503"/>
		<updated>2012-05-29T04:29:18Z</updated>

		<summary type="html">&lt;p&gt;James Jacobs: Created page with &amp;quot;Can anyone please supply the necessary #defines for the new tags (WINDOW_PopupGadget, etc.)? As matters now stand noone can add this feature to their programs :-(&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Can anyone please supply the necessary #defines for the new tags (WINDOW_PopupGadget, etc.)? As matters now stand noone can add this feature to their programs :-(&lt;/div&gt;</summary>
		<author><name>James Jacobs</name></author>
	</entry>
</feed>