home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / rxdlg11.zip / rxcapp.INF (.txt) < prev    next >
OS/2 Help File  |  1995-03-03  |  34KB  |  980 lines

  1.  
  2. ΓòÉΓòÉΓòÉ 1. Application Usage ΓòÉΓòÉΓòÉ
  3.  
  4. Rexx Dialog allows REXX scripts to present an enduser with a PM interface, 
  5. allowing him to use the mouse and keyboard to manipulate scrolling lists of 
  6. text, menus, sliders, buttons, etc, as well as being able to arrange all of 
  7. these in multiple windows that also can be manipulated with the mouse and 
  8. keyboard. 
  9.  
  10. RX.EXE is an application that launches a REXX script written for Rexx Dialog. 
  11. RXDLG.DLL is the REXX function library that makes the PM interface possible. 
  12.  
  13. It's also possible to utilize RXDLG.DLL in your own C applications (ie, just 
  14. like RX.EXE does).  By doing so, this makes it very easy to add a REXX 
  15. interface to your application.  In fact, it's easier than if you tried to add 
  16. such an interface from scratch because RXDLG has functions your C app can call 
  17. which you'd probably have to duplicate if you wrote your own REXX interface. 
  18. When your app uses RXDLG.DLL, it inherits all of the Rexx Dialog commands, and 
  19. therefore any REXX script that your app launches can open PM windows with PM 
  20. controls and do message loops, etc.  But, RXDLG.DLL also easily allows your app 
  21. to add new REXX commands which your app has its own functions to handle. 
  22.  
  23.  
  24. ΓòÉΓòÉΓòÉ 1.1. App requirements ΓòÉΓòÉΓòÉ
  25.  
  26. There are a few mandatory things that your app must be and do.  They are: 
  27.  
  28.  1. Your app must be a Presentation Manager app.  RXDLG.DLL can't be used by a 
  29.     windowed or full-screen app. 
  30.  
  31.  2. The thread that is going to launch the REXX script must call PM's 
  32.     WinInitialize() to get an anchor block, and WinCreateMsgQueue() to get a 
  33.     message queue.  The handle of the anchor block must be stored in the Hab 
  34.     field of your app's REXXSPEC.  A REXXSPEC is a special structure defined by 
  35.     Rexx Dialog (in RX.H) which RXDLG.DLL automatically creates and makes 
  36.     available to your app. 
  37.  
  38.  3. The thread must open a PM standard (ie, frame and client) window and place 
  39.     the handle of the client in the REXXSPEC's Hwnd field.  The ID of this 
  40.     client, and the IDs of any direct children of it (ie, not children of 
  41.     children) should be less than 7680.  This then becomes the "Main Window" 
  42.     into which any windows opened by a REXX script open.  Alternately, if you 
  43.     want the REXX script to create its own Main Window (ie, on the Desktop), 
  44.     then instead of setting the REXXSPEC's Hwnd field, you must supply an icon 
  45.     for the Main Window's CLOSE ICON in your executable's resource (ie, .RC 
  46.     file).  This icon must have an ID of 256. 
  47.  
  48.  4. If your app wishes to add new REXX commands (ie, in addition to the Rexx 
  49.     Dialog commands), you must fill in the REXXSPEC's Cmds, Prefix, and 
  50.     Handlers fields with a string containing the new commands, and an array of 
  51.     pointers to the functions in your app which handle those commands. 
  52.  
  53.  5. The thread must call RXDLG's RexxSet() once to initialize the REXX 
  54.     environment.  Afterward, the app can launch REXX scripts, and use various 
  55.     RXDLG.DLL functions. 
  56.  
  57.  6. Before ending, the thread should call RexxFree() to free up any REXX 
  58.     resources.  Also the message queue created in step 1 should be freed with 
  59.     WinDestroyMsgQueue() and PM resources freed with WinTerminate(). 
  60.  
  61. In order to avoid name conflicts with RXDLG.DLL, it's recommended that you not 
  62. name any of your functions or variables starting with the letters Rexx or Dlg. 
  63.  
  64. RXDLG.DLL utilizes window message IDs of WM_USER to WM_USER+49.  Therefore, if 
  65. your app defines message IDs of its own, it should start those IDs at 
  66. WM_USER+50. 
  67.  
  68.  
  69. ΓòÉΓòÉΓòÉ 1.2. RX.EXE ΓòÉΓòÉΓòÉ
  70.  
  71. RX.EXE is an example of an app that does the minimum required setup.  It then 
  72. calls the RXDLG function RexxRunScript() which launches and runs a REXX script. 
  73. RexxRunScript is passed the null-terminated name of the REXX script to execute. 
  74. (You supply the desired script name as an argument when running RX.EXE from the 
  75. command line.  Remember, you can run PM apps from an OS/2 command line too). 
  76. When RexxRunScript() returns, the REXX script will have been completely 
  77. executed.  RX.EXE simply ends after the script has been executed once (doing 
  78. the necessary cleanup). 
  79.  
  80. RX.EXE doesn't open a Main Window on behalf of the REXX script.  So, it has an 
  81. icon resource (RX.ICO) with an ID of 256 bound to its executable (ie, via 
  82. RX.RC). 
  83.  
  84. RX.EXE doesn't add any REXX commands of its own, so it doesn't set the REXXSPEC 
  85. Cmds, Prefix, and Handlers fields. 
  86.  
  87. RX.EXE also uses the RXDLG function DlgErrMsg() to display an error message for 
  88. any error number returned by RexxSet, and DlgMsgStr() to display any error 
  89. messages that RX.EXE creates and wants to present to the user.  These 2 
  90. functions simply pop up a PM message box to display the error message. 
  91.  
  92. Examine the source code RX.C to see an example of an app that uses RXDLG.DLL to 
  93. launch a Rexx Dialog REXX script, and use it to launch any of the example REXX 
  94. scripts included in this archive. 
  95.  
  96.  
  97. ΓòÉΓòÉΓòÉ 1.3. Supplying a Main Window ΓòÉΓòÉΓòÉ
  98.  
  99. You may wish to supply a Main Window into which all of the REXX script's 
  100. windows open.  For example, your app will most likely have its own window 
  101. anyway, and you may want to keep all your app's windows in one place, including 
  102. ones opened by REXX scripts that your app launches, so that minimizing your 
  103. app's window also minimizes all of those child windows.  Furthermore, a MODAL 
  104. window opened by the script will disable your app window and its children. 
  105.  
  106. Note that your app can open windows, but still choose to not supply a Main 
  107. Window on behalf of the REXX scripts.  The scripts will simply open their own 
  108. Main Window on the Desktop.  But, if your app windows are opened by the thread 
  109. that calls RexxRunScript(), then you should follow the guidelines in App Window 
  110. Procedure. 
  111.  
  112. RX2.C adds code to RX.C in order to demonstrate supplying a Main Window. 
  113.  
  114. In order to properly support the script opening MODAL windows, the Main Window 
  115. must have the class style CS_HITTEST (and may have other styles of your 
  116. choosing) and its window procedure must call the RXDLG function DlgCheckModal() 
  117. when receiving a WM_HITTEST message. 
  118.  
  119. Furthermore, for proper updating of the display, the WM_PAINT handling for the 
  120. Main Window should clear the invalid portion of its window using its desired 
  121. background color.  (This eliminates a need to handle WM_ERASEBACKGROUND). 
  122. After this, you may then do any other painting that is desired in your Main 
  123. Window. 
  124.  
  125. RX2.C launches the REXX script whenever you double-click the mouse 1 button. 
  126. This is done in the Main Window's window procedure myClientWndProc(), for the 
  127. WM_BUTTON1DBLCLK case.  Since it's possible for the window procedure to be 
  128. called while the REXX script is executing (ie, because the user may have 
  129. manipulated our Main Window while the script was doing user interaction with 
  130. RXDLG), and we don't want to launch another Rexx Dialog script while one is 
  131. already running, we first check that the REXXSPEC's EXECUTING Flag is not set. 
  132. RexxRunScript() sets this Flag when a script is running, and clears this after 
  133. a script is done executing. 
  134.  
  135. It's also possible to subsequently open a Main Window on behalf of the script 
  136. after you've already called RexxSet() to setup the REXX interface.  You could 
  137. open the Main Window before calling RexxRunScript(), storing the client handle 
  138. in RexxSpec.Hwnd, and after RexxRunScript() returns, close the Main Window and 
  139. clear (ie, set to 0) RexxSpec.Hwnd. 
  140.  
  141.  
  142. ΓòÉΓòÉΓòÉ 1.4. App Window Procedure ΓòÉΓòÉΓòÉ
  143.  
  144. Even if you don't supply a Main Window, but if the thread that creates the 
  145. message queue and calls RexxRunScript opens other application windows, then 
  146. it's possible that your application window procedure could be called while a 
  147. REXX script is executing.  The scenario would be as follows -- the REXX script 
  148. creates one or more windows and then calls RXDLG to do user interaction (ie, 
  149. Operation 0 or 1).  The user then manipulates one of your application windows 
  150. while the script is "sleeping" in RXDLG.  Your app window procedure gets called 
  151. with the appropriate message for the user's action (ie, if he double-clicks the 
  152. mouse 1 button, then your window procedure receives a WM_BUTTON1DBLCLK 
  153. message). 
  154.  
  155. If it's important that your window procedure know if there's a REXX script 
  156. being executed, check the EXECUTING Flag of REXXSPEC's Flags field.  This will 
  157. be set if there's a REXX script executing. 
  158.  
  159. One thing that you shouldn't do when there's a REXX script executing is call 
  160. RexxRunScript() to launch another REXX script.  Doing so may result in the 
  161. second REXX script closing any windows opened by the first script, when the 
  162. second script ends, and vice versa.  Your app should only execute one REXX 
  163. script at a time. 
  164.  
  165. Another caveat is receiving a WM_CLOSE message, while a REXX script is running, 
  166. for the Main Window that you supply to the script.  You could ignore this 
  167. message by returning 0 if you want to allow the script to end of its own 
  168. accord.  Or if you want to close up your Main Window, abort the REXX script, 
  169. and allow any WinGetMsg()/WinDispatchMsg() loop that you do in your app to drop 
  170. out (due to WM_QUIT), you can simply let the OS/2 WinDefWindowProc() handle the 
  171. WM_CLOSE.  If the script is written to EXIT when RXDLG returns RXID = -99 (or 
  172. any negative value), then the script should properly abort, and your app will 
  173. get its WM_QUIT.  If you close any Main Window that you've supplied to the 
  174. script, then you should clear (ie, set to 0) REXXSPEC's Hwnd.  (If your app is 
  175. going to terminate now, this isn't really necessary).  You should clear this 
  176. field when processing the WM_DESTROY message of your window procedure for that 
  177. Main Window. 
  178.  
  179.  
  180. ΓòÉΓòÉΓòÉ 1.5. App REXX Commands ΓòÉΓòÉΓòÉ
  181.  
  182. You can add your own REXX commands to the set of standard REXX commands (ie, 
  183. PARSE, LEFT, etc) as well as Rexx Dialog commands (ie, RXDLG, RXSET, etc).  For 
  184. each new REXX command that you add, you must specify a function in your app to 
  185. be called for that command.  Whenever RXDLG.DLL detects one of these commands 
  186. being issued in the REXX script, it calls your app function associated with 
  187. that command, passing any arguments (ie, additional text supplied by the script 
  188. after the command). 
  189.  
  190. In setting up a REXX interface for your app, you need to decide if you'd like a 
  191. prefix on your command set.  For example, you'll note that all of the Rexx 
  192. Dialog commands begin with the 2 letters RX.  This makes it easy to distinguish 
  193. Rexx Dialog commands from standard REXX commands as well as labels in the REXX 
  194. script.  (ie, When writing a script, it's easier to avoid using any label that 
  195. starts with RX, rather than having to remember every Rexx Dialog command so 
  196. that you don't inadvertently use one of those for a label.  This would cause 
  197. the REXX interpreter to misinterpret what may be intended to be a call to a 
  198. Rexx Dialog function).  It's recommended that you choose a prefix for your 
  199. command set.  We'll arbitrarily choose the prefix APP for our example command 
  200. set.  You need to place a pointer to this null-terminated string in REXXSPEC's 
  201. Prefix field.  The string must be in upper case.  For example: 
  202.  
  203. RexxSpec.Prefix = "APP"; 
  204.  
  205. If you don't want any prefix on your commands, leave the Prefix field cleared. 
  206.  
  207. Next, you need to decide what particular commands you'd like to create.  For 
  208. example, let's say that we want a REXX command called APPADD which will add 2 
  209. numbers supplied by the script, and return the sum to the script.  Here's how 
  210. we want the script to call APPADD to add 5 and 384. 
  211.  
  212. APPADD 5 384 
  213.  
  214. Let's say that we also want a REXX command called APPSUBTRACT which will 
  215. subtract 2 numbers supplied by the script, and return the difference to the 
  216. script.  Here's how we want the script to call APPSUBTRACT to subtract 5 from 
  217. 384. 
  218.  
  219. APPSUBTRACT 384 5 
  220.  
  221. Now that we have our new command set (consisting of 2 commands), we need to set 
  222. the REXXSPEC's Cmds field to point to a UCHAR array containing these commands. 
  223. The first UCHAR of the array will be a count of how many characters are in the 
  224. first command name, followed by that first command name.  In other words, the 
  225. strings are stored in Pascal style.  Then, the second command's length, and 
  226. name follows.  After the last command, there must be a 0 UCHAR to mark the end 
  227. of the commands in the array.  The command names must be in upper case.  They 
  228. are not null-terminated.  Do not include the prefix on the commands (ie, the 
  229. first command is ADD, not APPADD).  Here's how we setup the array for our 
  230. command set. 
  231.  
  232. UCHAR cmdArray[] = {3, 'A', 'D', 'D', 8, 'S', 'U', 'B', 'T', 'R', 'A', 'C', 
  233. 'T', 0 }; 
  234.  
  235. RexxSpec.Cmds = &cmdArray[0]; 
  236.  
  237. Finally we need to setup an array of pointers to our functions for those 
  238. commands.  Let's say that we have a function called Add2() to handle the APPADD 
  239. command, and a function called Subtract2() to handle the APPSUBTRACT command. 
  240. The functions must be listed in the same order as the commands are specified in 
  241. the Cmds array (ie, since we specified APPADD first, then Add2() is first in 
  242. the functions array).  Here's how we setup the array for our functions. 
  243.  
  244. PFUNC cmdFuncs[] = { Add2, Subtract2 }; 
  245.  
  246. RexxSpec.Handlers = &cmdFuncs[0]; 
  247.  
  248. Now let's talk about those functions.  When a function is called, REXXSPEC's 
  249. FromStr points to any text that was supplied by the script.  Using our above 
  250. example of the script calling APPADD, when Add2() is called, RexxSpec.FromStr 
  251. points to the null-terminated string "5 384".  REXX does not supply numeric 
  252. variables in binary form.  Rather, REXX always supplies args the way that any 
  253. argv[] args are supplied to your main() function; as ascii strings.  Of course, 
  254. you get all of the args that the REXX script supplies, as one long string that 
  255. you have to parse.  For example, to add the two numbers, we have to parse the 
  256. string into its separate elements of "5" and "384", and convert those two 
  257. strings to binary (as you might using atoi) to perform the addition.  When we 
  258. return the sum to the REXX script, we have to convert that binary value back 
  259. into an ascii string (as you might using itoa). 
  260.  
  261. RXDLG.DLL has several functions for parsing the arg string, and functions for 
  262. converting ascii strings to binary and vice versa.  For example, 
  263. DlgAsciiToNum() parses an ascii string for the next numeric value, converts it 
  264. to binary, and optionally returns an updated pointer to the parsed string (ie, 
  265. points to after the numeric value which has been converted).  This makes it 
  266. very trivial to parse and convert the arg string passed to Add2(). 
  267. DlgAsciiToNum() takes 3 args; the pointer to the string to parse (in this case 
  268. RexxSpec.FromStr), a handle where to place the updated pointer (or 0 if we 
  269. don't want that updated pointer returned), and a format char which is 'H' if 
  270. the value is expressed as hexidecimal, 'B' if the value is expressed as binary, 
  271. or anything else means that the value is expressed in decimal.  Since we expect 
  272. the script to supply decimal values, we'll pass a format of 0.  Because we have 
  273. to parse 2 numbers from the string, we'll ask for the updated pointer to be 
  274. returned when we parse the first number, and we'll have it returned in 
  275. RexxSpec.FromStr. 
  276.  
  277. Finally, we need to return the value to the script.  RXDLG.DLL has a function 
  278. called RexxReturnNum() which converts a binary value to an ascii string, and 
  279. indicates that we want that returned to the script in the special variable RC. 
  280.  
  281. So, here's our Add2() function. 
  282.  
  283. VOID EXPENTRY Add2(VOID) 
  284.   LONG num1, num2; 
  285.  
  286.   /* Get first number */ 
  287.   num1 = DlgAsciiToNum(RexxSpec.FromStr, &RexxSpec.FromStr, 0); 
  288.  
  289.   /* Get second number */ 
  290.   num2 = DlgAsciiToNum(RexxSpec.FromStr, 0, 0); 
  291.  
  292.   /* Add numbers and return it to the script */ 
  293.   RexxReturnNum(num1+num2); 
  294.  
  295. The Subtract2() function will be the same except that we'll return num1-num2. 
  296.  
  297. The REXX script gets its return in the special REXX variable RC as so: 
  298.  
  299. APPADD 5 384 
  300. RXSAY '5 + 384 =' RC 
  301.  
  302. Suppose you wanted to return the value in the REXX variable SUM instead of RC. 
  303. The function RexxSetNumVar() will convert the binary value to an ascii string, 
  304. and set the value of a REXX variable to that.  The variable name that you 
  305. supply must be in upper case, and a legal REXX variable name (including stem 
  306. and compound variable names).  So, let's substitute RexxSetNumVar() for 
  307. RexxReturnNum(). 
  308.  
  309. VOID EXPENTRY Add2(VOID) 
  310.   LONG num1, num2; 
  311.  
  312.   /* Get first number */ 
  313.   num1 = DlgAsciiToNum(RexxSpec.FromStr, &RexxSpec.FromStr, 0); 
  314.  
  315.   /* Get second number */ 
  316.   num2 = DlgAsciiToNum(RexxSpec.FromStr, 0, 0); 
  317.  
  318.   /* Add numbers and return it to the script */ 
  319.   RexxSetNumVar("SUM", num1+num2); 
  320.  
  321. Now the REXX script gets its return in the REXX variable SUM (case is 
  322. irrelevant) as so: 
  323.  
  324. APPADD 5 384 
  325. RXSAY '5 + 384 =' Sum 
  326.  
  327. By not returning the value in RC, you can then use RC to indicate an error 
  328. condition.  For example, let's say that the Subtract2() function wants to 
  329. indicate an error if the second number is larger than the first (ie, a negative 
  330. result would be flagged as an error).  DlgMsgStr() allows your function to 
  331. return an error message or number (for RC, which is otherwise a null string or 
  332. 0 for success) to the script.  It also displays that error message in a PM 
  333. message box if the display level that you specify is lower than the severity 
  334. level set by RXERR.  Finally it raises a FAILURE in the REXX script. 
  335.  
  336. VOID EXPENTRY Subtract2(VOID) 
  337.   LONG num1, num2; 
  338.  
  339.   /* Get first number */ 
  340.   num1 = DlgAsciiToNum(RexxSpec.FromStr, &RexxSpec.FromStr, 0); 
  341.  
  342.   /* Get second number */ 
  343.   num2 = DlgAsciiToNum(RexxSpec.FromStr, 0, 0); 
  344.  
  345.   /* Check if num1 < num2.  If so, then return an error. We arbitrarily choose 
  346. an error number of ERRAPP+DISPLAYLEVEL, and a display level of DISPLAYLEVEL 
  347. (defined in RX.H) */ 
  348.   if (num1 < num2) 
  349.   { 
  350.     DlgMsgStr("Second number smaller than first", ERRAPP+DISPLAYLEVEL, 
  351. DISPLAYLEVEL); 
  352.     return; 
  353.   } 
  354.  
  355.   /* Subtract numbers and return it to the script in the variable "ANSWER.0" */ 
  356.   RexxSetNumVar("ANSWER.0", num1-num2); 
  357.  
  358. Now the REXX script can check for an error.  (Assume the script wants error 
  359. messages instead of numbers -- ie, it hasn't set RXERR to return numbers, and 
  360. therefore RC = "" for success rather than 0). 
  361.  
  362. APPSUBTRACT 384 5 
  363. IF RC <> "" THEN RXSAY RC 
  364. ELSE RXSAY '384 - 5 =' Answer.0 
  365.  
  366. Note:  Case is irrelevant when the REXX script calls one of your app's REXX 
  367.        functions.  For example, 
  368.  
  369. AppAdd 384 5 
  370.  
  371. would achieve the same result as APPADD.
  372.  
  373. RX3.C adds code to RX.C to demonstrate adding the above 2 REXX commands. 
  374.  
  375. TESTRX3.CMD is a REXX script that tests those commands.  It makes one call to 
  376. APPADD and one call to APPSUBTRACT, printing out the results of those calls. 
  377. Then, if you press the ENTER key, another call to APPSUBTRACT is made, with 
  378. args that will cause Subtract2() to return its error message. 
  379.  
  380. The following sections detail the RXDLG.DLL functions that your script can 
  381. utilize in fetching and setting the values of REXX variables, parsing args, 
  382. converting strings to binary values and vice versa, setting/displaying error 
  383. messages and numbers, etc. 
  384.  
  385.  
  386. ΓòÉΓòÉΓòÉ 1.5.1. RexxSkipSpaces ΓòÉΓòÉΓòÉ
  387.  
  388. Template       RexxSkipSpaces(); 
  389.  
  390. Description    Skips any blank spaces in the string that RexxSpec.FromStr 
  391.                points to, updating RexxSpec.FromStr to point to the next 
  392.                non-blank character (could be the terminating null byte).  This 
  393.                is useful when parsing the arg string from a REXX script into 
  394.                separate arguments where spaces may be separating the arguments. 
  395.  
  396.  
  397. ΓòÉΓòÉΓòÉ 1.5.2. RexxParseArg ΓòÉΓòÉΓòÉ
  398.  
  399. Template       length = RexxParseArg(); 
  400.  
  401. Description    Extracts the next arg in the string pointed to by 
  402.                RexxSpec.FromStr, up to a | character or the terminating null 
  403.                byte, and copies that arg to the buffer pointed to by 
  404.                RexxSpec.InStr.  Leading and trailing blanks are trimmed off of 
  405.                the extracted arg.  Updates RexxSpec.FromStr to point past the 
  406.                extracted arg.  Returns the length of the extracted arg (ie, 
  407.                will be 0 if there was no arg to extract).  This can be used to 
  408.                extract args where a | character is used as a separator, such as 
  409.                the way that RXSAY separates the Message arg from the optional 
  410.                Type and Heading args. 
  411.  
  412.                Note:  Since FromStr and InStr point to the same buffer, and may 
  413.                       overlap, once you've extracted an arg and then wish to 
  414.                       save it beyond another call to RexxParseArg(), you should 
  415.                       copy the null-terminated arg that InStr points to, to 
  416.                       some other buffer.  You can use OutStr as that buffer if 
  417.                       you don't need to call RexxParseArg2() or RexxSetVar() 
  418.                       before you're done with the arg.
  419.  
  420. Returns        UCHAR length 
  421.  
  422.  
  423. ΓòÉΓòÉΓòÉ 1.5.3. RexxParseArg2 ΓòÉΓòÉΓòÉ
  424.  
  425. Template       length = RexxParseArg2(); 
  426.  
  427. Description    Extracts the next arg in the string pointed to by 
  428.                RexxSpec.FromStr, up to a space or the terminating null byte, 
  429.                and copies that arg to the buffer pointed to by RexxSpec.OutStr. 
  430.                Leading and trailing blanks are trimmed off of the extracted 
  431.                arg.  Updates RexxSpec.FromStr to point past the extracted arg. 
  432.                Returns the length of the extracted arg (ie, will be 0 if there 
  433.                was no arg to extract).  This can be used to extract args where 
  434.                one or more spaces are used as a separator, such as extracting a 
  435.                numeric value. 
  436.  
  437. Returns        UCHAR length 
  438.  
  439.  
  440. ΓòÉΓòÉΓòÉ 1.5.4. RexxParseArg3 ΓòÉΓòÉΓòÉ
  441.  
  442. Template       length = RexxParseArg3(); 
  443.  
  444. Description    Extracts the next arg in the string pointed to by 
  445.                RexxSpec.FromStr, up to a space or the terminating null byte, 
  446.                and copies that arg to the buffer pointed to by RexxSpec.InStr. 
  447.                Leading and trailing blanks are trimmed off of the extracted 
  448.                arg.  If the arg is enclosed in quotes, then everything in 
  449.                between the quotes is extracted (ie, the arg can have embedded 
  450.                as well as leading and trailing, spaces).  Updates 
  451.                RexxSpec.FromStr to point past the extracted arg.  Returns the 
  452.                length of the extracted arg (ie, will be 0 if there was no arg 
  453.                to extract).  This can be used to extract args where either one 
  454.                or more spaces are used as a separator, such as extracting a 
  455.                numeric value, or args where the script wants to allow embedded 
  456.                spaces (and therefore the arg is enclosed in a set of quotes) 
  457.                such as how the WindowTitle arg is specified in RXDLG. 
  458.  
  459.                Note:  When REXX passes an arg to an app, it "eats" the outer 
  460.                       set of quotes.  Therefore, it's necessary to use a second 
  461.                       set of quotes around the arg.  For example, in order for 
  462.                       your app to receive the string "hello there" (ie, with 
  463.                       the quotes), then the script must specify '"hello 
  464.                       there"'.  RexxParseArg3 will recognize double or single 
  465.                       quotes (ie, so "'hello there'" would achieve the same result).
  466.  
  467.                Note:  Since FromStr and InStr point to the same buffer, and may 
  468.                       overlap, once you've extracted an arg and then wish to 
  469.                       save it beyond another call to RexxParseArg(), you should 
  470.                       copy the null-terminated arg that InStr points to, to 
  471.                       some other buffer.  You can use OutStr as that buffer if 
  472.                       you don't need to call RexxParseArg2() or RexxSetVar() 
  473.                       before you're done with the arg.
  474.  
  475. Returns        UCHAR length 
  476.  
  477.  
  478. ΓòÉΓòÉΓòÉ 1.5.5. RexxReturnNum ΓòÉΓòÉΓòÉ
  479.  
  480. Template       RexxReturnNum(number); 
  481.  
  482. Description    Takes the binary number, converts it to an ascii string, and 
  483.                returns it to the script in the special variable RC, without 
  484.                causing a FAILURE in the REXX script.  This may be used by a 
  485.                function which wishes to return a numeric value, and the 
  486.                function doesn't need to reserve RC to return an error number 
  487.                (ie, the function doesn't do anything that would necessitate 
  488.                reporting an error to the script). 
  489.  
  490.                This function clears RexxSpec.InStr, which indicates to 
  491.                RXDLG.DLL that the RC value is to be set to the string that 
  492.                RexxSpec.ErrStr points to.  So, you should not call any function 
  493.                that references RexxSpec.InStr such as RexxParseArg(), 
  494.                RexxParseArg3(), RexxFetchVar(), or RexxFetchStemVar(), nor 
  495.                should your function reference RexxSpec.InStr.  It's best to 
  496.                call RexxReturnNum() only when your function is prepared to 
  497.                return immediately after. 
  498.  
  499. Args           LONG number 
  500.  
  501.  
  502. ΓòÉΓòÉΓòÉ 1.5.6. RexxSetNumVar ΓòÉΓòÉΓòÉ
  503.  
  504. Template       error = RexxSetNumVar(var_name, value); 
  505.  
  506. Description    Converts the binary value to an ascii (numeric) string, and sets 
  507.                the specified REXX variable to that value.  This is used to set 
  508.                a REXX variable in the script to some numeric value. 
  509.  
  510.                Note:  This may only be called by the same thread that launched 
  511.                       the script with RexxRunScript().
  512.  
  513. Args           UCHAR * var_name -- a pointer to the null-terminated name of the 
  514.                REXX variable.  Must be upper case.  Can be a stem or compound 
  515.                variable name. 
  516.  
  517.                LONG val -- the signed value to set the REXX variable to. 
  518.  
  519. Returns        UCHAR error -- 0=success, non-zero is an error in setting the 
  520.                REXX variable. 
  521.  
  522.                Note:  It's not necessary to display an error message, nor setup 
  523.                       an error return to the script.  RXDLG.DLL takes care of 
  524.                       that.  Your function merely needs to check for a non-zero 
  525.                       return, and if encountered, abort whatever it's doing and return.
  526.  
  527.  
  528. ΓòÉΓòÉΓòÉ 1.5.7. RexxSetVar ΓòÉΓòÉΓòÉ
  529.  
  530. Template       error = RexxSetVar(var_name); 
  531.  
  532. Description    Sets the specified REXX variable to the string contained in the 
  533.                buffer that RexxSpec.OutStr points to.  This is used to set a 
  534.                REXX variable in the script to some value (numeric or 
  535.                otherwise).  Before calling RexxSetVar(), you must copy the 
  536.                desired, null-terminated string to the buffer pointed to 
  537.                RexxSpec.OutStr.  (Setting the first byte of RexxSpec.OutStr to 
  538.                0, ie, nulling the buffer, causes the REXX variable to be set to 
  539.                a null string).  You must not copy more than 255 bytes to the 
  540.                buffer. 
  541.  
  542.                Note:  This may only be called by the same thread that launched 
  543.                       the script with RexxRunScript().
  544.  
  545. Args           UCHAR * var_name -- a pointer to the null-terminated name of the 
  546.                REXX variable.  Must be upper case.  Can be a stem or compound 
  547.                variable name. 
  548.  
  549. Returns        UCHAR error -- 0=success, non-zero is an error in setting the 
  550.                REXX variable. 
  551.  
  552.                Note:  It's not necessary to display an error message, nor setup 
  553.                       an error return to the script.  RXDLG.DLL takes care of 
  554.                       that.  Your function merely needs to check for a non-zero 
  555.                       return, and if encountered, abort whatever it's doing and return.
  556.  
  557.  
  558. ΓòÉΓòÉΓòÉ 1.5.8. RexxFetchVar ΓòÉΓòÉΓòÉ
  559.  
  560. Template       error = RexxFetchVar(var_name); 
  561.  
  562. Description    Fetches the value of the specified REXX variable (ie, whatever 
  563.                value the REXX script has set that variable to), and copies that 
  564.                value string into the buffer pointed to by RexxSpec.InStr. 
  565.                Resets RexxSpec.FromStr to RexxSpec.InStr (ie, resets it to 
  566.                point to the fetched value string so that string can be parsed 
  567.                with RexxParseArg(), RexxParseArg2(), or RexxParseArg3()). 
  568.  
  569.                Note:  Fetching a variable's value overwrites the original arg 
  570.                       string that was passed to your function from the script. 
  571.                       It's best to parse the original arg string before 
  572.                       fetching any variable values.  You can use 
  573.                       RexxSpec.OutStr as a 256 byte temporary buffer to hold 
  574.                       any strings you wish to save while fetching values.
  575.  
  576.                Note:  This may only be called by the same thread that launched 
  577.                       the script with RexxRunScript().
  578.  
  579. Args           UCHAR * var_name -- a pointer to the null-terminated name of the 
  580.                REXX variable.  Must be upper case.  Can be a stem or compound 
  581.                variable name. 
  582.  
  583. Returns        UCHAR error -- 0=success, non-zero is an error in fetching the 
  584.                REXX variable.  If the REXX script has failed to initialize the 
  585.                variable to some value, then this is flagged as an error. 
  586.  
  587.                Note:  It's not necessary to display an error message, nor setup 
  588.                       an error return to the script.  RXDLG.DLL takes care of 
  589.                       that.  Your function merely needs to check for a non-zero 
  590.                       return, and if encountered, abort whatever it's doing and return.
  591.  
  592.  
  593. ΓòÉΓòÉΓòÉ 1.5.9. RexxFetchStemVar ΓòÉΓòÉΓòÉ
  594.  
  595. Template       error = RexxFetchStemVar(var_name, stem); 
  596.  
  597. Description    Fetches the value of the specified REXX variable (ie, whatever 
  598.                value the REXX script has set that variable to), and copies that 
  599.                value string into the buffer pointed to by RexxSpec.InStr. 
  600.                Resets RexxSpec.FromStr to RexxSpec.InStr (ie, resets it to 
  601.                point to the fetched value string so that string can be parsed 
  602.                with RexxParseArg(), RexxParseArg2(), or RexxParseArg3()).  The 
  603.                difference from RexxFetchVar() is that the binary stem arg is 
  604.                appended to the var_name in order to create a stem variable. 
  605.                So, this function is used to specifically fetch a stem 
  606.                variable's value.  For example, assume that you wish to fetch 
  607.                the value of the variable MyVar.30: 
  608.  
  609.                error = RexxFetchStemVar("MYVAR", 30); 
  610.  
  611.                The variable name should be limited to 22 characters. 
  612.  
  613.                It's also possible to fetch a compound variable, if var_name 
  614.                already has one stem on it.  For example, assume that you wish 
  615.                to fetch the value of the variable MyVar.0.30: 
  616.  
  617.                error = RexxFetchStemVar("MYVAR.0", 30); 
  618.  
  619.                Note:  Fetching a variable's value overwrites the original arg 
  620.                       string that was passed to your function from the script. 
  621.                       It's best to parse the original arg string before 
  622.                       fetching any variable values.  You can use 
  623.                       RexxSpec.OutStr as a 256 byte temporary buffer to hold 
  624.                       any strings you wish to save while fetching values.
  625.  
  626.                Note:  This may only be called by the same thread that launched 
  627.                       the script with RexxRunScript().
  628.  
  629. Args           UCHAR * var_name -- a pointer to the null-terminated name of the 
  630.                REXX variable.  Must be upper case. 
  631.  
  632.                ULONG stem -- the stem that is appended to the variable name. 
  633.  
  634. Returns        UCHAR error -- 0=success, non-zero is an error in fetching the 
  635.                REXX variable.  If the REXX script has failed to initialize the 
  636.                variable to some value, then this is flagged as an error. 
  637.  
  638.                Note:  It's not necessary to display an error message, nor setup 
  639.                       an error return to the script.  RXDLG.DLL takes care of 
  640.                       that.  Your function merely needs to check for a non-zero 
  641.                       return, and if encountered, abort whatever it's doing and return.
  642.  
  643.  
  644. ΓòÉΓòÉΓòÉ 1.5.10. RexxAppendStem ΓòÉΓòÉΓòÉ
  645.  
  646. Template       ptr = RexxAppendStem(var_name, buffer, stem); 
  647.  
  648. Description    Copies the var_name to the buffer, adding the stem.  The buffer 
  649.                should be large enough to hold the final, null-terminated 
  650.                variable name.  This may be used to create a variable name that 
  651.                is to be passed to RexxFetchVar(), RexxSetVar(), or 
  652.                RexxSetNumVar().  For example, to create the variable name 
  653.                MYVAR.0 in a buffer: 
  654.  
  655.                UCHAR buffer[8]; 
  656.                RexxAppendStem("MYVAR", &buffer[0], 0); 
  657.  
  658.                A pointer to the end of the new variable name (ie, the address 
  659.                of its null byte) is returned.  This can be used to find the 
  660.                length of the string by subtracting it from the buffer arg 
  661.                passed to RexxAppendStem. 
  662.  
  663. Args           UCHAR * var_name -- a pointer to the null-terminated name of the 
  664.                REXX variable. 
  665.  
  666.                UCHAR * buffer -- a pointer to the buffer where the new variable 
  667.                name is created. 
  668.  
  669.                ULONG stem -- the stem that is appended to the new variable 
  670.                name. 
  671.  
  672. Returns        UCHAR * ptr -- a pointer to the null byte of the new variable 
  673.                name. 
  674.  
  675.  
  676. ΓòÉΓòÉΓòÉ 1.5.11. DlgAsciiToNum ΓòÉΓòÉΓòÉ
  677.  
  678. Template       number = DlgAsciiToNum(source, &updatedPtr, format); 
  679.  
  680. Description    Converts the source string (ie, points to a numeric string) to a 
  681.                32-bit binary value.  (This is essentially a 32-bit version of 
  682.                atoi).  Skips leading spaces on the source.  If updatedPtr is 
  683.                not 0 (ie, it's a handle to UCHAR *), then the updated pointer 
  684.                (ie, points to after the converted numeric string) is returned. 
  685.                This is useful for making multiple calls to DlgAsciiToNum in 
  686.                order to parse several numeric args from one arg string.  The 
  687.                format arg is 'H' if the source string was specified in 
  688.                hexidecimal (for example, "3FF0").  Format is 'B' if the source 
  689.                string was expressed in binary "bits" (for example, 
  690.                "0011111111110000" is the binary equivalent of hex "3FF0").  Any 
  691.                other value for format means that the source string is expressed 
  692.                in decimal. 
  693.  
  694. Args           UCHAR * source -- points to the numeric string to be converted. 
  695.  
  696.                UCHAR ** updatedPtr -- a handle to where the updated UCHAR * is 
  697.                returned.  If 0, then the updated pointer isn't returned. 
  698.  
  699.                UCHAR format -- 'H' is hexidecimal, 'B' is binary, any other is 
  700.                decimal. 
  701.  
  702. Returns        LONG number 
  703.  
  704.  
  705. ΓòÉΓòÉΓòÉ 1.5.12. DlgNumToAscii ΓòÉΓòÉΓòÉ
  706.  
  707. Template       ptr = DlgNumToAscii(number, buffer, flag); 
  708.  
  709. Description    Converts the binary number into a null-terminated ascii numeric 
  710.                string, storing it in the buffer.  (This is a 32-bit version of 
  711.                itoa).  The buffer must be large enough to hold the converted 
  712.                string.  Flag is a 1 if commas are desired after every third 
  713.                digit (ie, the way a human might write the number).  Flag is 0 
  714.                if no commas are desired.  (Commas should not be used if the 
  715.                resulting string is going to be used to set the value of a REXX 
  716.                variable which will be used in some mathematical way.  REXX 
  717.                doesn't like commas in numeric values that it must perform math 
  718.                upon).  A pointer to the end of the converted string (ie, the 
  719.                address of its null byte) is returned.  This can be used to find 
  720.                the length of the string by subtracting it from the buffer arg 
  721.                passed to DlgNumToAscii. 
  722.  
  723. Args           LONG number -- the signed binary value to be converted. 
  724.  
  725.                UCHAR * source -- points to the buffer where the numeric string 
  726.                is created. 
  727.  
  728.                UCHAR flag -- 1 if commas are desired, 0 otherwise. 
  729.  
  730. Returns        UCHAR * ptr -- a pointer to the null byte of the converted 
  731.                string. 
  732.  
  733.  
  734. ΓòÉΓòÉΓòÉ 1.5.13. RexxSet ΓòÉΓòÉΓòÉ
  735.  
  736. Template       error = RexxSet(); 
  737.  
  738. Description    This must be called once when setting up RXDLG.DLL for use by 
  739.                the app.  RexxSpec.Hab must first be set to a PM anchor block, 
  740.                and if your app adds its own REXX commands, it's best to setup 
  741.                the Cmds, Handlers, and Prefix fields of the REXXSPEC also prior 
  742.                to calling RexxSet. 
  743.  
  744. Returns        ULONG error -- 0 if success, non-zero if an error.  If there's 
  745.                an error, it is up to your script to display an error message to 
  746.                the enduser.  You can call DlgErrMsg() to have the DLL post a PM 
  747.                message box containing an appropriate error message.  The errors 
  748.                that RexxSet() returns are "Window registration failed." (3) or 
  749.                "Can't install REXX." (4).  These are described in the Errors 
  750.                section of the Rexx Dialog 1.0 manual, under the discussion of 
  751.                errors that aren't related to Rexx Dialog commands (ie, the 
  752.                bottom of the page). 
  753.  
  754.  
  755. ΓòÉΓòÉΓòÉ 1.5.14. RexxFree() ΓòÉΓòÉΓòÉ
  756.  
  757. Template       RexxFree(); 
  758.  
  759. Description    Closes down the REXX interface.  This will also cause any 
  760.                currently executing REXX script to abort.  This must be called 
  761.                once before the app ends. 
  762.  
  763.  
  764. ΓòÉΓòÉΓòÉ 1.5.15. RexxRunScript ΓòÉΓòÉΓòÉ
  765.  
  766. Template       error = RexxRunScript(scriptname); 
  767.  
  768. Description    This executes a REXX script, where scriptname points to the 
  769.                null-terminated name of the script to execute.  It sets the 
  770.                EXECUTING Flag of REXXSPEC while the script is executing, and 
  771.                clears that Flag when the script is done.  It then returns an 
  772.                error indication.  The error number is also returned in 
  773.                RexxSpec.ErrNum. 
  774.  
  775.                RexxRunScript() may end up passing on messages to any app window 
  776.                procedure, for windows opened by the same thread that called 
  777.                RexxRunScript(), while the REXX script is executing.  It may 
  778.                also call any REXX command functions that your app added, 
  779.                whenever those commands are issued by the script. 
  780.  
  781. Args           UCHAR * scriptname -- the null-terminated name of the script to 
  782.                run.  It should be fully qualified (ie, with the drive and path) 
  783.                if the script is not in the current directory. 
  784.  
  785. Returns        ULONG error -- 0 if the script successfully executed, non-zero 
  786.                otherwise. 
  787.  
  788.                Note:  It's not necessary to display an error message. 
  789.                       RXDLG.DLL takes care of that.
  790.  
  791.  
  792. ΓòÉΓòÉΓòÉ 1.5.16. DlgErrMsg ΓòÉΓòÉΓòÉ
  793.  
  794. Template       DlgErrMsg(msgNum, errNum); 
  795.  
  796. Description    Displays an appropriate error message for any error number 
  797.                returned by RexxSet(), and sets RexxSpec.ErrNum to the specified 
  798.                errNum. 
  799.  
  800. Args           ULONG msgNum -- the error number returned by RexxSet(). 
  801.  
  802.                ULONG errNum -- the error number that you want RexxSpec.ErrNum 
  803.                to be set to.  It is recommended that you add the constant 
  804.                ERRAPP to msgNum.  That will result in error numbers that are 
  805.                unique from anything else returned by RXDLG.DLL functions such 
  806.                as RexxRunScript(). 
  807.  
  808.  
  809. ΓòÉΓòÉΓòÉ 1.5.17. DlgMsgStr ΓòÉΓòÉΓòÉ
  810.  
  811. Template       DlgMsgStr(errMsg, errNum, displayLevel); 
  812.  
  813. Description    Returns the specified error message or error number (depending 
  814.                upon whether the script has indicated that it wants messages or 
  815.                numbers returned for errors) to the script (in the special 
  816.                variable RC).  It also displays the error message if the script 
  817.                has set the display level at least as high as the specified 
  818.                displayLevel.  It also causes a FAILURE in the REXX script. 
  819.  
  820.                The error number should be 20000 (ie, ERRAPP) or greater since 
  821.                RXDLG.DLL reserves lower error numbers, which it may return to 
  822.                the script.  In this way, a script can always distinguish a 
  823.                problem with your app (ie, calling RexxSet or RexxRunScript, or 
  824.                an error returned by your own REXX functions) versus an error 
  825.                returned by one of the Rexx Dialog functions.  Furthermore, it's 
  826.                recommended that you set any error numbers generated by your 
  827.                REXX functions to be greater than ERRAPP+DISPLAYLEVEL.  Each 
  828.                error returned by your functions should be a unique number, as 
  829.                this number gets passed on to the REXX script (if it asks for 
  830.                error numbers returned). 
  831.  
  832.                Your app can also call DlgMsgStr whenever a REXX script is not 
  833.                executing (ie, to display error messages for functions not 
  834.                related to REXX), in which case, a message box with the error 
  835.                message is always presented. 
  836.  
  837. Args           UCHAR * errMsg -- the null-terminated error message to return to 
  838.                the script. 
  839.  
  840.                ULONG msgNum -- the error number to return to the script. 
  841.  
  842.                ULONG displayLevel -- the display level for this error.  A 
  843.                message box will be displayed if the script has set the display 
  844.                level to at least this amount (using RXERR).  Otherwise, no 
  845.                message box is displayed.  (ie, It will up to the REXX script to 
  846.                post an error indication to the enduser, as the script will 
  847.                receive notice of this error). 
  848.  
  849.  
  850. ΓòÉΓòÉΓòÉ 1.5.18. DlgCheckModal ΓòÉΓòÉΓòÉ
  851.  
  852. Template       value = DlgCheckModal(hwnd, mp1); 
  853.  
  854. Description    This is only called during the WM_HITTEST processing in a window 
  855.                procedure that services windows opened by the same thread that 
  856.                has called RexxRunScript().  It allows the script to properly 
  857.                utilize MODAL windows.  The app windows should have the class 
  858.                style CS_HITTEST. 
  859.  
  860. Args           HWND hwnd -- the window handle arg passed to the app's window 
  861.                procedure from OS/2. 
  862.  
  863.                MPARAM mp1 -- the message parameter 1 arg passed to the app's 
  864.                window procedure from OS/2. 
  865.  
  866. Returns        MRESULT value -- the value that your window procedure's 
  867.                WM_HITTEST case returns (to OS/2). 
  868.  
  869.  
  870. ΓòÉΓòÉΓòÉ 1.6. Returning RC values to the REXX script ΓòÉΓòÉΓòÉ
  871.  
  872. The special RC REXX variable is usually used to return error messages or 
  873. numbers to the REXX script.  (The script uses RXERR to set whether it wants 
  874. messages or numbers returned for errors).  If a function executes successfully, 
  875. it sets RC to either a null string (ie, "") if messages are to be returned, or 
  876. 0 if numbers are to be returned.  Non-null strings or non-zero values for RC 
  877. indicate that the function encountered some error.  In this case, RC is either 
  878. an error messsage or an error (non-zero) number.  The script can then check the 
  879. RC value after each call to a Rexx Dialog or your app's own REXX commands to 
  880. determine whether an error occurred or not. 
  881.  
  882. Your app must use DlgMsgStr() to display error messages that your app creates 
  883. and wishes to return to the script.  (DlgErrMsg() may be optionally used to 
  884. display messages corresponding to error numbers returned by RexxSet()).  This 
  885. function properly sets up the error return for RC, and it also causes the 
  886. FAILURE flag to be set in the REXX script (so that the script can use SIGNAL ON 
  887. FAILURE to automatically jump to error handling whenever your app returns an 
  888. error).  Also, DlgMsgStr() takes care of automatically displaying the error 
  889. message in a PM message box if the script desires that (ie, the script uses 
  890. RXERR to set the display level to determine which error messages if any it 
  891. wants automatically displayed). 
  892.  
  893. Note:  Your REXX function need do nothing if it wants to return a successful RC 
  894.        value.  RXDLG.DLL defaults to returning that, until such time as your 
  895.        app specifically calls DlgMsgStr() to set an error return.
  896.  
  897. If your REXX function always succeeds (ie, there's no scenario in which an 
  898. error condition may arise), then you can instead use the RC variable to return 
  899. a value from your function.  Use the RexxReturnNum() function to return a 
  900. numeric value to the script. 
  901.  
  902. Note:  RexxReturnNum() is passed a signed long, so if you're passing a ULONG 
  903.        instead, you're limited to a range of 0 to 2,147,483,647.
  904.  
  905. RexxReturnNum() clears the RexxSpec.InStr pointer, (which indicates to 
  906. RXDLG.DLL that the RC value is to be set to the string that RexxSpec.ErrStr 
  907. points to).  So, after calling RexxReturnNum(), you should not call any 
  908. function that references RexxSpec.InStr such as RexxParseArg(), 
  909. RexxParseArg3(), RexxFetchVar(), RexxFetchStemVar(), DlgMsgStr(), or 
  910. DlgErrMsg(), nor should your function reference RexxSpec.InStr.  It's best to 
  911. call RexxReturnNum() only when your function is prepared to return immediately 
  912. after. 
  913.  
  914. RexxReturnNum() does not raise the FAILURE flag in the script. 
  915.  
  916. If your function wishes to return a string (rather than a numeric value) to a 
  917. script (without causing a FAILURE in the script), simply set RexxSpec.ErrStr to 
  918. point to the desired string, clear RexxSpec.InStr, and return.  For example, 
  919. here is a function that simply returns the string "Hello" to the script. 
  920.  
  921. VOID EXPENTRY ReturnHello(VOID) 
  922.   /* Set ErrStr to point to the desired string. Obviously, it can't be in a 
  923. local buffer (ie, on the stack) because we need to return it */ 
  924.   RexxSpec.ErrStr = "Hello"; 
  925.  
  926.   /* Clear InStr to let RXDLG.DLL know that we want to return ErrStr in the RC 
  927. variable */ 
  928.   RexxSpec.InStr = 0; 
  929.  
  930.   /* Return control back to the script */ 
  931.   return; 
  932.  
  933. For example, if your app associated ReturnHello() with a APPHELLO command, the 
  934. script would do: 
  935.  
  936. APPHELLO 
  937. /* Print the returned "Hello" */ 
  938. RXSAY RC 
  939.  
  940.  
  941. ΓòÉΓòÉΓòÉ 1.7. InStr and OutStr ΓòÉΓòÉΓòÉ
  942.  
  943. The RexxSpec pointers InStr and OutStr each point to a (different) 256 byte 
  944. buffer.  These pointers are valid ONLY while RXDLG.DLL is calling one of your 
  945. app's REXX functions.  You can determine that this is the case by checking the 
  946. OutStr pointer.  If it's not zero, then InStr and OutStr are valid.  Initially, 
  947. InStr points to the arg string that was received by the script.  You can use 
  948. these buffers for any purpose that you desire, although some of the RXDLG.DLL 
  949. functions also use these buffers.  RexxParseArg(), RexxParseArg3(), 
  950. RexxFetchVar(), and RexxFetchStemVar() use InStr (and its buffer), and 
  951. RexxParseArg2() and RexxSetVar() use OutStr (and its buffer).  It's best to not 
  952. alter these 2 pointers if you're going to be calling the preceding RXDLG.DLL 
  953. functions. 
  954.  
  955.  
  956. ΓòÉΓòÉΓòÉ 1.8. Documentation ΓòÉΓòÉΓòÉ
  957.  
  958. If you want to provide an online book (ie, .INF file, like this one) detailing 
  959. your app's REXX interface, the best approach is to create an INF file that 
  960. lists only those new REXX commands that your app implements.  For example, 
  961. RX3.IPF is example IPFC source code that documents the 2 commands APPADD and 
  962. APPSUBTRACT that we added to RX3.C.  It has a heading page, followed by a page 
  963. for each REXX command.  The layout is similiar to that used for the online book 
  964. for Rexx Dialog (ie, RX.INF). 
  965.  
  966. Then, create a desktop object that invokes OS/2's VIEW.EXE utility.  For the 
  967. Parameters field of the object, add RX.INF and the name of the INF file 
  968. describing your new functions.  For example: 
  969.  
  970. RX+RX3 
  971.  
  972. The result is a book that combines the 2 INF files into one.