home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / rxlbox13.zip / rxlbox.cmd < prev    next >
OS/2 REXX Batch file  |  1998-03-01  |  157KB  |  3,540 lines

  1. /**********************************************************************/
  2. /*                                                                    */
  3. /* /----------------------------------------------------------------\ */
  4. /* | RxLBox.CMD - a textmode menu program for OS/2 written in REXX  | */
  5. /* |                         Version 1.30                           | */
  6. /* |        (c) Copyright 1996, 1997, 1998 by Bernd Schemmer        | */
  7. /* \----------------------------------------------------------------/ */
  8. /*                                                                    */
  9. /* Author                                                             */
  10. /* ======                                                             */
  11. /*                                                                    */
  12. /*   Bernd Schemmer                                                   */
  13. /*   Baeckerweg 48                                                    */
  14. /*   60316 Frankfurt                                                  */
  15. /*   Germany                                                          */
  16. /*   CompuServe: 100104,613                                           */
  17. /*   Internet: 100104.613@compuserve.com                              */
  18. /*                                                                    */
  19. /* ------------------------------------------------------------------ */
  20. /* Description:                                                       */
  21. /* ============                                                       */
  22. /*                                                                    */
  23. /* RXLBOX is a powerfull textmode menu program for OS/2 written       */
  24. /* in plain REXX. RXLBOX supports cursor keys, function keys and a    */
  25. /* command line for navigation. Nested menus are ok. RxLBox also      */
  26. /* supports menus for user input.                                     */
  27. /*                                                                    */
  28. /* No additional DLLs are necessary, even REXXUTIL is not used!       */
  29. /*                                                                    */
  30. /* All with simple, plain REXX and ANSI sequences. Therefore you can  */
  31. /* use RxLBOX even if booted from diskette. This is very useful for   */
  32. /* CID installations for example.                                     */
  33. /*                                                                    */
  34. /* RXLBOX is completly configurable using a menu description file     */
  35. /* (including menus, messages, online help screens, function keys     */
  36. /* and macros). RXLBOX also supports an external message handling     */
  37. /* routine.                                                           */
  38. /*                                                                    */
  39. /* Beginning with version 1.30 RXLBOX also supports the EXTPROC       */
  40. /* feature of the CMD.EXE.                                            */
  41. /*                                                                    */
  42. /* ------------------------------------------------------------------ */
  43. /* Usage                                                              */
  44. /* =====                                                              */
  45. /*                                                                    */
  46. /* Usage from within a REXX program:                                  */
  47. /* ---------------------------------                                  */
  48. /*                                                                    */
  49. /*   userInput = RxLBox( {inputChannel} {,menuSections} {,quiet} )    */
  50. /*                                                                    */
  51. /* Usage from the command line:                                       */
  52. /* ----------------------------                                       */
  53. /*                                                                    */
  54. /*   RxLBox {/I:inputChannel} {/S:quiet}                              */
  55. /*          {/M:menuSection1} {...} {/M:MenuSection#}                 */
  56. /*          {/EXTPROC}                                                */
  57. /*                                                                    */
  58. /*   Note:                                                            */
  59. /*     If calling RxLBox from the command line, you must enclose all  */
  60. /*     parameter that contain blanks in '"' or "'".                   */
  61. /*     Example:                                                       */
  62. /*                                                                    */
  63. /*       RxLBox /I:"My Menu File" /M:"My Main Menu"                   */
  64. /*                                                                    */
  65. /*     or                                                             */
  66. /*                                                                    */
  67. /*       RxLBox "/I:My Menu File" "/M:My Main Menu"                   */
  68. /*                                                                    */
  69. /*     You can use the parameter in any order. For duplicate          */
  70. /*     parameters RxLBox uses only the last parameter.                */
  71. /*     (except the parameter '/M', see below)                         */
  72. /*                                                                    */
  73. /* Where:                                                             */
  74. /* ------                                                             */
  75. /*                                                                    */
  76. /*   inputChannel                                                     */
  77. /*     This is the file or queue with the menu descriptions           */
  78. /*     for RxLBox. The format for this parameter is:                  */
  79. /*                                                                    */
  80. /*       fileName                                                     */
  81. /*                                                                    */
  82. /*     or                                                             */
  83. /*                                                                    */
  84. /*       QUEUE:{queueName}                                            */
  85. /*                                                                    */
  86. /*     'queueName' is the name of the queue; the default is the       */
  87. /*     current active REXX queue. This part of the parameter is       */
  88. /*     optional.                                                      */
  89. /*                                                                    */
  90. /*     The name of the input channel can not contain leading          */
  91. /*     or trailing blanks but imbedded blanks are ok.                 */
  92. /*                                                                    */
  93. /*     The default input channel is the menu description file         */
  94. /*     "MAIN.MEN" either in the current directory or in the           */
  95. /*     directory with RXLBOX.CMD (in this order).                     */
  96. /*     This parameter is optional.                                    */
  97. /*                                                                    */
  98. /*   menuSections                                                     */
  99. /*   menuSection1 ... MenuSection#                                    */
  100. /*     This parameter is used to init the internal menu stack.        */
  101. /*     The values are treated as menu names and pushed onto the       */
  102. /*     internal menu stack. The name of the last menu is the menu     */
  103. /*     that RxLBox shows after startup.                               */
  104. /*     The first occurence of this parameter specifies the main       */
  105. /*     menu; this menu name is available about the variable           */
  106. /*     '!curMainMenu' in the menu description file.                   */
  107. /*                                                                    */
  108. /*     Examples:                                                      */
  109. /*                                                                    */
  110. /*       RxLBox /I:TEST.MEM                                           */
  111. /*     or                                                             */
  112. /*       myRC = RxLbox( 'TEST.MEM' )                                  */
  113. /*                                                                    */
  114. /*     In this case RxLBox does not push a menu entry onto the        */
  115. /*     internal stack. It shows the default menu 'MAINMENU' after     */
  116. /*     startup. Pressing ESC within this menu ends the program.       */
  117. /*                                                                    */
  118. /*                                                                    */
  119. /*       RxLBox /I:TEST.MEM /M:MYMENU                                 */
  120. /*     or                                                             */
  121. /*       myRC = RxLBox( 'TEST.MEM', 'MYMENU' )                        */
  122. /*                                                                    */
  123. /*     In this case RxLBox does not push a menu entry onto the        */
  124. /*     internal stack. It shows the menu 'MYMENU' after               */
  125. /*     startup. Pressing ESC within this menu ends the program.       */
  126. /*                                                                    */
  127. /*                                                                    */
  128. /*       RxlBox /I:TEST.MEN /M:MainMenu /M:SubMenu                    */
  129. /*     or                                                             */
  130. /*       myRC = RxlBox( 'TEST.MEN', 'MainMenu,SubMenu' )              */
  131. /*                                                                    */
  132. /*     In this case, RxLBox pushs the menu entry 'MainMenu' onto the  */
  133. /*     menu stack and starts with the menu 'SubMenu'. If the user     */
  134. /*     presses ESC, RxLBox jumps back into the menu 'MainMenu'.       */
  135. /*                                                                    */
  136. /*                                                                    */
  137. /*       RxLbox /I:TEST.MEM /M:MainMenu /M:SubMenu1 /M:SubMenu2       */
  138. /*     or                                                             */
  139. /*       myRC = RxLbox( 'TEST.MEM', 'MainMenu,SubMenu1,SubMenu2'      */
  140. /*                                                                    */
  141. /*     In this case, RxLBox pushs then menu entries 'MainMenu' and    */
  142. /*     'SubMenu1' onto the stack and starts with the menu 'SubMenu2'. */
  143. /*     The first ESC then brings the user back to the menu 'SubMenu1' */
  144. /*     and a further ESC brings him back to the menu 'MainMenu'.      */
  145. /*                                                                    */
  146. /*                                                                    */
  147. /*     Menu names can not contain leading or trailing blanks but      */
  148. /*     imbedded blanks are ok. This parameter is optional.            */
  149. /*     The only default menu used is the menu "MAINMENU".             */
  150. /*                                                                    */
  151. /*                                                                    */
  152. /*   quiet                                                            */
  153. /*     if 1: don't show in progress messages                          */
  154. /*     any other value: show in progress messages (default)           */
  155. /*     This parameter is optional.                                    */
  156. /*                                                                    */
  157. /*                                                                    */
  158. /*   EXTPROC                                                          */
  159. /*     use this parameter if you use the EXTPROC feature of the       */
  160. /*     CMD.EXE. In this case you can omnit the parameter /I:.         */
  161. /*                                                                    */
  162. /*     To use this feature, use the extension .CMD for your menu      */
  163. /*     file and use the EXTPROC statement as first line of the menu   */
  164. /*     file. The format of the EXTPROC statement MUST be:             */
  165. /*                                                                    */
  166. /*          EXTPROC rxlbox_name %0 /EXTPROC {further_parms}           */
  167. /*                                                                    */
  168. /*     rxlbox_name is the name (with or without path) of RXLBOX.CMD   */
  169. /*                                                                    */
  170. /*     %0 is replaced by the CMD.EXE with the fully qualified name    */
  171. /*     of the menu file.                                              */
  172. /*                                                                    */
  173. /*     /EXTPROC is a necessary keyword.                               */
  174. /*                                                                    */
  175. /*     further_parms may be additional static parameter for           */
  176. /*     RXLBOX.CMD (This parameter is optional).                       */
  177. /*                                                                    */
  178. /*     NOTE: DO ONLY ADD FURTHER PARAMETER AFTER /EXTPROC!            */
  179. /*                                                                    */
  180. /*     To call the menu either use                                    */
  181. /*                                                                    */
  182. /*          menuFile                                                  */
  183. /*                                                                    */
  184. /*     or                                                             */
  185. /*                                                                    */
  186. /*          menuFile {furtherParameter}                               */
  187. /*                                                                    */
  188. /*     (see the SAMPLE5.CMD for an example)                           */
  189. /*                                                                    */
  190. /* RxLBox returns if called from within a REXX program:               */
  191. /* ----------------------------------------------------               */
  192. /*                                                                    */
  193. /*   either the choosen entry value from the input channel            */
  194. /*   or "WARNING: warningNo"                                          */
  195. /*   or "ERROR: errorNo : errorText"                                  */
  196. /*   or an empty string if the user didn't select an entry            */
  197. /*                                                                    */
  198. /*   Defined warning codes:                                           */
  199. /*   ----------------------                                           */
  200. /*                                                                    */
  201. /*     warningNo   description                                        */
  202. /*     --------------------------------------------------             */
  203. /*        2          menu aborted by the user with CTRL-C             */
  204. /*                                                                    */
  205. /*   Defined error codes:                                             */
  206. /*   --------------------                                             */
  207. /*                                                                    */
  208. /*       see below for the defined error numbers and messages         */
  209. /*                                                                    */
  210. /* RxLBox returns if called from the command line:                    */
  211. /* -----------------------------------------------                    */
  212. /*                                                                    */
  213. /*   0 - okay                                                         */
  214. /*   else error, in this case the error message is written to STDERR  */
  215. /*                                                                    */
  216. /*                                                                    */
  217. /* Samples                                                            */
  218. /* =======                                                            */
  219. /*                                                                    */
  220. /*   Take a look at the included samples SAMPLE?.CMD (where ? is a    */
  221. /*   number between 1 and 5) to see how it works.                     */
  222. /*   Use RXLBOX.MEN as template for other menus; RXLBOX.MEN contains  */
  223. /*   all possible entries for a menu file. All entries are explained  */
  224. /*   in this file.                                                    */
  225. /*   Call RXLBOX without a parameter from the command line to test    */
  226. /*   the examples.                                                    */
  227. /*   See also the file SETVARS.INI for a real live menu used in our   */
  228. /*   CID installations.                                               */
  229. /*                                                                    */
  230. /* ------------------------------------------------------------------ */
  231. /* Generell notes                                                     */
  232. /* ==============                                                     */
  233. /*                                                                    */
  234. /*   This program needs the OS/2 program ANSI.EXE.                    */
  235. /*   If the display is not in the 80x25 character mode,               */
  236. /*   RxLBox uses the OS/2 program MODE.EXE to switch to the 80x25     */
  237. /*   character mode at program start and to restore the display mode  */
  238. /*   at program end.                                                  */
  239. /*   RxLBox always turns the ANSI support on. But this should not     */
  240. /*   be a great problem because by default ANSI is always on in       */
  241. /*   OS/2 sessions.                                                   */
  242. /*                                                                    */
  243. /*                                                                    */
  244. /*   The names of all internal routines in RXLBOX.CMD begin with the  */
  245. /*   prefix I!.__.                                                    */
  246. /*   The only exceptions are the routines 'ShowWorkingMessage',       */
  247. /*   'EnvValue', and 'WaitForAKey'.                                   */
  248. /*   These are the only routines that you can call in a REXX          */
  249. /*   statement in the menu descriptions.                              */
  250. /*   See the file RXLBOX.MEN for the usage description of this        */
  251. /*   routines.                                                        */
  252. /*                                                                    */
  253. /* ------------------------------------------------------------------ */
  254. /* Technical information                                              */
  255. /* =====================                                              */
  256. /*                                                                    */
  257. /*   see the file RXLBOX.MEN for the format and possible entries      */
  258. /*   for a menu file.                                                 */
  259. /*                                                                    */
  260. /*   The programming style of this program is not a good one.         */
  261. /*   That's because one main goal while developing RxLBox was         */
  262. /*   avoiding a token image greater than 64K.                         */
  263. /*   (Because the OS/2 REXX interpreter can only save the token       */
  264. /*    image in the EAs if it's smaller than 64K.)                     */
  265. /*                                                                    */
  266. /*   Do not attach an icon to this file. You also shouldn't create    */
  267. /*   Extended Attributes other then the EAs created by the REXX       */
  268. /*   interpreter for this file. If you do attach EAs to this file,    */
  269. /*   the REXX interpreter can not save the token image in the EAs     */
  270. /*   of the file (the token image needs about 63.000 bytes in the     */
  271. /*   EAs).                                                            */
  272. /*                                                                    */
  273. /* ------------------------------------------------------------------ */
  274. /* Messages                                                           */
  275. /* ========                                                           */
  276. /*                                                                    */
  277. /* The following is a list of all messages used by RxLBox.            */
  278. /*                                                                    */
  279. /*                                                                    */
  280. /* Hardcoded messages                                                 */
  281. /* ------------------                                                 */
  282. /*                                                                    */
  283. /* Note: You can not override these messages!                         */
  284. /*                                                                    */
  285. /* Message                                                            */
  286. /*  No    Message text                      Parameter                 */
  287. /* ------------------------------------------------------------------ */
  288. /*  97    ERROR: 97 : errortext             "errortext" is the value  */
  289. /*                                          of !curRC                 */
  290. /*                                                                    */
  291. /*  98    ERROR: 98 : RXLBOX is an                                    */
  292. /*        OS/2 REXX program                                           */
  293. /*                                                                    */
  294. /*                                                                    */
  295. /* Userdefined messages                                               */
  296. /* --------------------                                               */
  297. /*                                                                    */
  298. /* Note: You can override these messages with your own messages       */
  299. /*       using an external message handling routine (see below)       */
  300. /*       If you use 'Global.__BaseMsgNo', you must add that value to  */
  301. /*       the message number!                                          */
  302. /*       (see GETMSG.CMD for an example external message handling     */
  303. /*        routine)                                                    */
  304. /*                                                                    */
  305. /* Message                                                            */
  306. /*  No    Default message text              Parameter                 */
  307. /* ------------------------------------------------------------------ */
  308. /*   1    (not used)                        -                         */
  309. /*                                                                    */
  310. /*   2    Inputfile %1 not found            %1 = name of the input    */
  311. /*                                               file                 */
  312. /*                                                                    */
  313. /*   3    Inputfile %1 is empty             %1 = name of the input    */
  314. /*                                               file                 */
  315. /*                                                                    */
  316. /*   4    Error opening the input file %1   %1 = name of the input    */
  317. /*                                               file                 */
  318. /*                                                                    */
  319. /*   5    InputQueue %1 does not exist      %1 = name of the input    */
  320. /*                                               queue                */
  321. /*                                                                    */
  322. /*   6    InputQueue %1 is empty            %1 = name of the input    */
  323. /*                                               queue                */
  324. /*                                                                    */
  325. /*   7    The line %1 of the input channel  %1 = line number          */
  326. /*        is invalid (The line reads: %2)   %2 = line contents        */
  327. /*                                                                    */
  328. /*   8    Menu %1 not found                 %1 = name of the menu     */
  329. /*                                                                    */
  330. /*   9    Menu %1 is empty                  %1 = name of the menu     */
  331. /*                                                                    */
  332. /*  10    Line %1: Menu %2 already defined  %1 = line number          */
  333. /*                                          %2 = name of the menu     */
  334. /*                                                                    */
  335. /*  11    (not used)                                                  */
  336. /*                                                                    */
  337. /*  12    Line %1: Macroname to long        %1 = line number          */
  338. /*                                                                    */
  339. /*  13    Invalid menu command found: %1    %1 = invalid menu command */
  340. /*                                                                    */
  341. /*  14    Line %1: Macro %2 already defined %1 = line number          */
  342. /*                                          %2 = name of the macro    */
  343. /*                                                                    */
  344. /*  15    Line %1: Keyword missing          %1 = line number          */
  345. /*                                                                    */
  346. /*  16    Line %1: Invalid MENUITEM/ACTION  %1 = line number          */
  347. /*        keyword found                                               */
  348. /*                                                                    */
  349. /*  17    Line %1: Invalid REXX statement,  %1 = line number          */
  350. /*        the line reads: %2                %2 = line contents        */
  351. /*                                                                    */
  352. /*  18    Line %1: Onlinehelp %2 already    %1 = line number          */
  353. /*        defined                           %2 = name of the online   */
  354. /*                                               help topic           */
  355. /*                                                                    */
  356. /*  19    Line %1: Onlinehelp to large      %1 = line number          */
  357. /*        (maximum is 14 lines)                                       */
  358. /*                                                                    */
  359. /*  20    Line %1: Invalid menu name        %1 = line number          */
  360. /*                                                                    */
  361. /*  21    Parameter %1 is invalid           %1 = invalid parameter    */
  362. /*                                                                    */
  363. /*  99    %1 error in line %2, rc = %3 %4   %1 = condition('C')       */
  364. /*                                          %2 = line number          */
  365. /*                                          %3 = rc                   */
  366. /*                                          %4 = add. information     */
  367. /*                                                                    */
  368. /* 100    Checking the parameter ...        -                         */
  369. /*                                                                    */
  370. /* 101    Reading the menu description ...  -                         */
  371. /*                                                                    */
  372. /* 102    Creating the menu structure ...   -                         */
  373. /*                                                                    */
  374. /* 103    Preparing the menu ...            -                         */
  375. /*                                                                    */
  376. /* 104    %1                                %1 = error message from   */
  377. /*                                          the #UserInput command    */
  378. /*                                                                    */
  379. /* 105    (not used)                        -                         */
  380. /*                                                                    */
  381. /* 106    (not used)                        -                         */
  382. /*                                                                    */
  383. /* 107    (not used)                        -                         */
  384. /*                                                                    */
  385. /* 108    (not used)                        -                         */
  386. /*                                                                    */
  387. /* 109    (not used)                        -                         */
  388. /*                                                                    */
  389. /* 110    List of all menu descriptions in  -                         */
  390. /*                                                                    */
  391. /* 111    Choose a menu from the list       -                         */
  392. /*                                                                    */
  393. /* 112    Your choice:                      -                         */
  394. /*                                                                    */
  395. /* 113    Press any key to continue         -                         */
  396. /*                                                                    */
  397. /* 114    List of all macros defined in     -                         */
  398. /*                                                                    */
  399. /* 115    *** Keyword %1 not defined for    %1 = keyword name         */
  400. /*        this menu!                                                  */
  401. /*                                                                    */
  402. /* 116    List of all menus called so far   -                         */
  403. /*                                                                    */
  404. /* 117    Choose a macro from the list      -                         */
  405. /*                                                                    */
  406. /* 118    Error evaluating %1               %1 = invalid REXX         */
  407. /*                                               statement            */
  408. /*                                                                    */
  409. /* ------------------------------------------------------------------ */
  410. /* History                                                            */
  411. /* =======                                                            */
  412. /*                                                                    */
  413. /*   V1.00  - 01.04.1996 /bs                                          */
  414. /*     - initial release                                              */
  415. /*                                                                    */
  416. /*   V1.10  - 01.09.1996 /bs                                          */
  417. /*                                                                    */
  418. /*    + corrections                                                   */
  419. /*     - corrected a bug in the handling of number commands           */
  420. /*     - in the previous version, entering a number greater or equal  */
  421. /*       than the number of the last menu more than one time          */
  422. /*       destroyed the status line. Fixed.                            */
  423. /*     - in the previous version, RxLBox didn't recognize the keys    */
  424. /*       ESC, ALT-F4 and ALT-X if entered after other keys. Fixed.    */
  425. /*     - added code to check the length of a macro name (max is 25)   */
  426. /*       (error message 12 is used in case of an invalid length)      */
  427. /*                                                                    */
  428. /*    + new features                                                  */
  429. /*     - added a continuation char to split an entry over multiple    */
  430. /*       lines                                                        */
  431. /*     - added the keyword "InputVar"                                 */
  432. /*     - added the keyword "OnInit"                                   */
  433. /*     - added the keyword "OnExit"                                   */
  434. /*     - added the keyword "OnMainInit"                               */
  435. /*     - added the keyword "OnMainExit"                               */
  436. /*     - added a level parameter to the #GOBACK command               */
  437. /*       (e.g. now you can say "jump 2 menu levels back")             */
  438. /*     - now you can return a string beginning with an asterix '*'    */
  439. /*       or a dash '#' to the calling program                         */
  440. /*       (Preceed the string with '^' to do this; use '^^' for        */
  441. /*        strings beginning with '^').                                */
  442. /*     - changed the behaviour of the REXXCMD and EXECUTECMD commands */
  443. /*       (see the description in the file RXLBOX.MEN)                 */
  444. /*     - RxLBox now clears the screen using the color from the key    */
  445. /*       CLS before executing an OS/2 command                         */
  446. /*     - added the variable !curMenu to REXX variables useable in     */
  447. /*       REXX statements                                              */
  448. /*     - now you can return strings in mixed case                     */
  449. /*     - made imbedded REXX statements in menu descriptions more save */
  450. /*       Now you can't read or change REXX variables used in RxLBOX   */
  451. /*       in the REXX statements used in menu descriptions. The only   */
  452. /*       REXX variables you can read (and change) in REXX statements  */
  453. /*       in menu descriptions are !curMenu, !curMenuAction,           */
  454. /*       and !curMenuEntry.                                           */
  455. /*       These variables are set but not used by RxLBox               */
  456. /*       For global REXX variables in REXX statements in menu         */
  457. /*       descriptions you can use the stem 'MenuDesc.'.               */
  458. /*                                                                    */
  459. /*     - added a real life example menu file (SAMPLE3*.*)             */
  460. /*                                                                    */
  461. /*   V1.20  - 01.12.1996 /bs                                          */
  462. /*                                                                    */
  463. /*    + corrections                                                   */
  464. /*     - corrected some spelling errors in the files                  */
  465. /*     - In the previous version RxLBox ignored the key HelpForF1 in  */
  466. /*       the DEFAULTMENU. Fixed.                                      */
  467. /*     - added a list of the used messages and the parameter for the  */
  468. /*       messages in the header of this file                          */
  469. /*                                                                    */
  470. /*    + new features                                                  */
  471. /*     - added the command #UserInput                                 */
  472. /*     - added the keyword StatusLine.# for every menu entry          */
  473. /*     - added code to check for duplicate menu entry definitions     */
  474. /*     - added the new error message number 104                       */
  475. /*     - added further exported REXX variables:                       */
  476. /*         !curPageNo                                                 */
  477. /*         !totalPageCount                                            */
  478. /*         !curLineNo                                                 */
  479. /*         !curEntryNo                                                */
  480. /*         !totalEntryCount                                           */
  481. /*     - added the (exported) routine EnvValue                        */
  482. /*     - enhanced the real life example menu file (SAMPLE3*.*)        */
  483. /*                                                                    */
  484. /*   V1.21  - 01.04.1997 /bs (internal release only)                  */
  485. /*                                                                    */
  486. /*    + corrections                                                   */
  487. /*     - corrected some bugs in the CTRL-C handling                   */
  488. /*     - in the previous version the description for the exported     */
  489. /*       REXX routine 'ShowWorkingMessage' in the file 'RXLBOX.MEM'   */
  490. /*       was wrong.                                                   */
  491. /*                                                                    */
  492. /*    + new features                                                  */
  493. /*     - added the exported variable !curMenuEntry1                   */
  494. /*     - added the variable "MenuDesc.__NoHalt"                       */
  495. /*       to change the behaviour for CTRL-C                           */
  496. /*     - added the (exported) routine WaitForAKey                     */
  497. /*     - added some add. parameter for the routine ShowWorkingMessage */
  498. /*     - added code to ignore keywords beginning with "PM_". These    */
  499. /*       keywords are reserved for a future PM version.               */
  500. /*                                                                    */
  501. /*   V1.22  - 01.05.1997 /bs                                          */
  502. /*                                                                    */
  503. /*    + corrections                                                   */
  504. /*                                                                    */
  505. /*    + new features                                                  */
  506. /*     - added the parameter for sub menus                            */
  507. /*     - now the three title lines are also updated after each        */
  508. /*       command execution or function key pressed                    */
  509. /*     - added further exported REXX variables:                       */
  510. /*         !curMainMenu                                               */
  511. /*     - added code to redefine the ESC key also                      */
  512. /*     - added the parameter -2 for the #GOBACK command               */
  513. /*     - added a new example for RxLBox (SAMPLE4.CMD)                 */
  514. /*       to show the usage of the additional /M parameter             */
  515. /*                                                                    */
  516. /*   V1.30 - 01.03.1998 /bs                                           */
  517. /*     - added support for the EXTPROC feature of the CMD.EXE         */
  518. /*     - added a new sample (SAMPLE5.CMD) to show the usage of the    */
  519. /*       EXTPROC feature                                              */
  520. /*                                                                    */
  521. /* ------------------------------------------------------------------ */
  522. /* Terms for using this version of RXLBOX                             */
  523. /* ======================================                             */
  524. /*                                                                    */
  525. /* This version is free for private use.                              */
  526. /* (see the file README.DOC for my distribution policy)               */
  527. /*                                                                    */
  528. /* ------------------------------------------------------------------ */
  529. /* Warranty Disclaimer                                                */
  530. /* ===================                                                */
  531. /*                                                                    */
  532. /* Bernd Schemmer makes no warranty of any kind, expressed or         */
  533. /* implied, including without limitation any warranties of            */
  534. /* merchantability and/or fitness for a particular purpose.           */
  535. /*                                                                    */
  536. /* In no event will Bernd Schemmer be liable to you for any           */
  537. /* additional damages, including any lost profits, lost savings, or   */
  538. /* other incidental or consequential damages arising from the use of, */
  539. /* or inability to use, this software and its accompanying documen-   */
  540. /* tation, even if Bernd Schemmer has been advised of the possibility */
  541. /* of such damages.                                                   */
  542. /*                                                                    */
  543. /* ------------------------------------------------------------------ */
  544. /* Copyright                                                          */
  545. /* =========                                                          */
  546. /*                                                                    */
  547. /* RXLBOX, the documentation for RXLBOX and all other related files   */
  548. /* are                                                                */
  549. /* -- Copyright 1996-1998 by Bernd Schemmer.  All rights reserved. -- */
  550. /*                                                                    */
  551. /*                                                                    */
  552. /* ------------------------------------------------------------------ */
  553. /*                                                                    */
  554. /**********************************************************************/
  555.  
  556.  
  557. /*
  558. RxLBox:
  559. */
  560.                     /* turn trace off                                 */
  561.                     /* (-> ignore the value of the environment        */
  562.                     /*     variable RXTRACE!                          */
  563.   i = trace( 'OFF' )
  564.  
  565. /* --------------------------- */
  566.  
  567.                     /* These are the exported REXX variables          */
  568.                     /* (-> exported REXX variables are REXX variables */
  569.                     /*     that you can use in menu descriptions)     */
  570.                     /*                                                */
  571.   exportedREXXVariables = '!curMenu !curMenuAction !curMainMenu',
  572.                           '!curMenuEntry !curMenuEntry1',
  573.                           '!curRC !curCmd !curPageno !totalPageCount',
  574.                           '!curLineNo !curEntryNo !totalEntryCount'
  575.  
  576.                     /* create a list of all global variables          */
  577.   exposeList = 'Global. Menu. ansi. ascii. help. msgStr. inputLines.' ,
  578.                '!ListMenu !HistoryMenu !MacroMenu !defaultMenu' ,
  579.                '!MainMenu !thisMenu !NextMenu !BackLevel UserResponse' ,
  580.                'MenuDesc.' exportedREXXVariables
  581.  
  582.                     /* init all global variables with ''              */
  583.   interpret "parse value '' with " exposeList menuNames
  584.  
  585.   exposeList = exposeList 'exportedREXXVariables'
  586.  
  587. /* --------------------------- */
  588.  
  589.                     /* get the source, call type and program name     */
  590.   parse source Global.__osV ,
  591.                Global.__cType ,
  592.                Global.__ProgName
  593.  
  594.                     /* check the operating system                     */
  595.   if Global.__osV <> 'OS/2' then
  596.   do
  597.                     /* invalid operating system, print an error       */
  598.                     /* message and end the program                    */
  599.                     /*                                                */
  600.                     /* Note: This is the only hardcode message in the */
  601.                     /*       program!                                 */
  602.     tLine = 'ERROR: 98 :' Global.__ProgName 'is an OS/2 REXX program'
  603.     if Global.__cType <> 'COMMAND' then
  604.       return tLine
  605.  
  606.                     /* the following two statements are only executed */
  607.                     /* if RxLBox is called from the command line!     */
  608.                     /* (-> only if global.__cType is 'COMMAND')       */
  609.     call LineOut , tLine
  610.     exit 255
  611.  
  612.   end /* if Global.__osV <> 'OS/2' then */
  613.  
  614. /* --------------------------- */
  615.  
  616.                     /* change & uncomment the next lines if you've    */
  617.                     /* got an external message handling routine       */
  618.  
  619.                     /* uncomment the next lines to test the included  */
  620.                     /* external message handling routine GETMSG       */
  621.                     /* The external routine is called with            */
  622.                     /*                                                */
  623.                     /*   call GetMsg msgNo ,, mP1, mp2, ... , mp9     */
  624.                     /*                                                */
  625.                     /* (Note the empty parameter after the msgNo      */
  626.                     /*  parameter!)                                   */
  627.                     /*                                                */
  628.                     /* msgNo is the message number; mp1 ... mp9 are   */
  629.                     /* the parameter for the message. mp1 ... mp9     */
  630.                     /* are optional (depending on the message).       */
  631.                     /* Message numbers start at                       */
  632.                     /*                                                */
  633.                     /*   global.__BaseMsgNO+1                         */
  634.                     /*                                                */
  635.                     /* (see GETMSG.CMD for an example)                */
  636.                     /*                                                */
  637.  
  638.                     /* 'Global.__GetMsgRoutine' contains the name of  */
  639.                     /* the external message handling routine.         */
  640.                     /* The external message handling routine can be   */
  641.                     /*   - a REXX program in the current directory    */
  642.                     /*   - a REXX program accessible about the PATH   */
  643.                     /*     variable                                   */
  644.                     /*   - a registered DLL routine                   */
  645.                     /* or                                             */
  646.                     /*   - a REXX routine in the macro space          */
  647. /*
  648.   Global.__GetMsgRoutine = 'GETMSG'
  649. */
  650.                     /* 'Global.__BaseMsgNo' contains the base message */
  651.                     /* number for the messages.                       */
  652.                     /* So the first message number is                 */
  653.                     /*                                                */
  654.                     /*    Global.__BaseMsgNO + 1                      */
  655.                     /*                                                */
  656.                     /* You can change this variable to any value you  */
  657.                     /* like. If Global.__BaseMsgNo is not defined,    */
  658.                     /* RxLBox uses 0 as base message number.          */
  659.                     /*                                                */
  660. /*
  661.   Global.__BaseMsgNo = '1800'
  662. */
  663.  
  664.  
  665. /* --------------------------- */
  666.  
  667.                     /* init the global menu data                      */
  668.   call I!.__IGData
  669.  
  670.                     /* save the name of the current queue             */
  671.   global.__OldQ = RxQueue( 'G' )
  672.  
  673.                     /* save the name of the current environment       */
  674.   global.__OldEnv = address()
  675.  
  676.                     /* make the CMD the current environment           */
  677.   address 'CMD'
  678.  
  679. /* --------------------------- */
  680.  
  681.                     /* install some error handler                     */
  682.   CALL   ON HALT NAME HALT1
  683.   SIGNAL ON SYNTAX
  684.  
  685.   SIGNAL OFF ERROR
  686.   SIGNAL OFF NOVALUE
  687.   SIGNAL OFF FAILURE
  688.  
  689. /* --------------------------- */
  690.                     /* get the parameter                              */
  691.   if Global.__cType = 'COMMAND' then
  692.   do
  693.                     /* RxLBox was called from the command line        */
  694.     parse upper arg thisArgs
  695.  
  696.                     /* check for EXTPROC statement                    */
  697.     if pos( '/EXTPROC', thisArgs ) <> 0 then
  698.     do
  699.                     /* split the arguments into filename and other    */
  700.                     /* arguments                                      */
  701.       parse var thisArgs dataFile '/EXTPROC' thisArgs
  702.  
  703.       dataFile = strip( strip( dataFile ), 'B', '"' )
  704.       if translate( right( dataFile, 4 ) ) <> '.CMD' then
  705.         dataFile = dataFile || '.CMD'
  706.  
  707.       dataFileName = filespec( 'N', dataFile ) 
  708.       if translate( right( dataFileName, 4 ) ) <> '.CMD' then
  709.         dataFileName = dataFileName || '.CMD'
  710.  
  711.                     /* now remove the filename added by the CMD.EXE   */
  712.       dataFileName = translate( datafilename )  
  713.       i = pos( dataFileName, translate( thisArgs ) )
  714.       j = length( dataFileName )
  715.       thisArgs = strip( substr( thisArgs,1, i-1 ) || ,
  716.                  substr( thisArgs,i+j ) )
  717.  
  718.                     /* now add the filename again                     */
  719.                     /* using the /I: parameter                        */
  720.       thisArgs = thisArgs '/I:' || '"'dataFile'"'
  721.     end /* if pos( '/EXTRPOC', thisArgs ) <> 0 then */
  722.     
  723.     do while thisargs <> ''
  724.  
  725.       parse value strip( thisArgs, "B" ) WITH curArg ThisArgs
  726.  
  727.       parse var curArg tc +1 .
  728.       if tc = '"' | tc = "'" then
  729.         parse value curArg thisArgs WITH (tc) curArg (tc) ThisArgs
  730.  
  731.       parse var curArg '/' argType ':' aValue
  732.  
  733.       parse var aValue tc +1 .
  734.       if tc = '"' | tc = "'" then
  735.         parse value aValue thisArgs WITH (tc) aValue (tc) ThisArgs
  736.  
  737.       select
  738.  
  739.                     /* /I: - select the input channel                 */
  740.         when argType = 'I' then
  741.           Global.__iDevice = aValue
  742.  
  743.                     /* /M: - init the menu history list               */
  744.         when argType = 'M' then
  745.           menuNames = MenuNames || aValue || '00'x
  746.  
  747.                     /* /S: - turn quiet mode on or off                */
  748.         when argType = 'S' then
  749.           Global.__Quiet = (aValue = 1)
  750.  
  751.                     /* else invalid parameter                         */
  752.         otherwise
  753.           call I!.__AbortProgram 21, curArg
  754.  
  755.       end /* select */
  756.  
  757.     end /* do while thisArgs <> '' */
  758.  
  759.   end /* if callType = 'COMMAND' then */
  760.   else
  761.   do
  762.                     /* RxLBox was called from another REXX program    */
  763.     parse upper arg Global.__iDevice ,,
  764.                     menuNameParam ,,
  765.                     Global.__Quiet
  766.  
  767.                     /* process the parameter 'menuNameParam'          */
  768.  
  769.     do while menuNameParam <> ''
  770.       parse var menuNameParam p1 ',' menuNameParam
  771.       menuNames = menuNames || strip( p1 ) || '00'x
  772.     end /* do forever */
  773.  
  774.   end /* else */
  775.  
  776. /* --------------------------- */
  777.                     /* check the parameter                            */
  778.  
  779.                     /* show an in progress message                    */
  780.   call ShowWorkingMessage I!.__GetMessage( 100 )
  781.  
  782.                     /* use the default main menu if the parameter for */
  783.                     /* the main menu is missing                       */
  784.   if menuNames = '' then
  785.     menuNames = !MainMenu
  786.  
  787.                     /* check the parameter                            */
  788.   Global.__iDevice = strip( Global.__iDevice )
  789.  
  790.                     /* use the default menu description file if the   */
  791.                     /* parameter for the inputchannel is missing      */
  792.   if Global.__iDevice = '' then
  793.   do
  794.                     /* search the default menu                        */
  795.                     /* search order is:                               */
  796.                     /*   1. current directory                         */
  797.                     /*   2. directory with RXLBOX.CMD                 */
  798.                     /*                                                */
  799.  
  800.     Global.__iDevice = directory() || '\' || Global.__defMenuName
  801.  
  802.     if stream( Global.__iDevice, 'c', 'QUERY EXIST' ) = '' then
  803.       Global.__iDevice = fileSpec( 'D', Global.__ProgName ) || ,
  804.                          fileSpec( 'P', Global.__ProgName ) || ,
  805.                          Global.__defMenuName
  806.   end /* if */
  807.  
  808. /* --------------------------- */
  809.                     /* show an in progress message                    */
  810.   call ShowWorkingMessage I!.__GetMessage( 101 )
  811.  
  812.                     /* read the lines from the input channel          */
  813.   call I!.__ReadMenuD Global.__iDevice
  814.  
  815.                     /* show an in progress message                    */
  816.   call ShowWorkingMessage I!.__GetMessage( 102 )
  817.  
  818.                     /* process the menu definitions                   */
  819.   menusFound = I!.__CreateMenues()
  820.  
  821. /* --------------------------- */
  822.                     /* install an error handler for CTRL-C            */
  823.   CALL   ON HALT
  824.  
  825. /* --------------------------- */
  826.                     /* show an in progress message                    */
  827.   call ShowWorkingMessage I!.__GetMessage( 103 )
  828.  
  829.                     /* create the initial menu stack                  */
  830.   i = 0
  831.   do until menuNames = ''
  832.     parse upper var MenuNames !thisMenu '00'x menuNames
  833.     if !thisMenu = '' then
  834.       iterate
  835.  
  836.                     /* check if the menu exist                        */
  837.     if Menu.!thisMenu.__NoOfEntries = '' then
  838.       call I!.__AbortProgram 8, !thisMenu
  839.  
  840.                     /* check if the menu is not empty                 */
  841.     if Menu.!thisMenu.__NoOfEntries <= 0 then
  842.       call I!.__AbortProgram 9, !thisMenu
  843.  
  844.                     /* add the menu to the menu stack                 */
  845.     i = i + 1
  846.     menuStack.i = strip( !thisMenu )
  847.  
  848.   end /* do until menuNames = '' */
  849.   menuStack.0 = i
  850.  
  851. /* --------------------------- */
  852.                     /* turn ANSI support on and                       */
  853.                     /* change the ANSI status                         */
  854.   call I!.__ChgAnsiStatus
  855.  
  856. /* --------------------------- */
  857.                     /* save the OnMainInit & OnMainExit code          */
  858.   !curMainMenu = menuStack.1
  859.   !curMenu = !thisMenu
  860.  
  861.   !MainExitCode = menu.!curMainMenu.__OnMainExit
  862.   !MainInitCode = menu.!curMainMenu.__OnMainInit
  863.  
  864.                     /* execute the OnMainInit code                    */
  865.   call I!.__ILine '?',, !MainInitCode
  866.   if !curRC <> '' then
  867.   do
  868.     global.__rc = 'ERROR: 97 :' !curRC
  869.     signal I!.__RxLBoxEnd1
  870.   end /* if !curRC <> '' then */
  871.  
  872.  
  873. /* --------------------------- */
  874.                     /* menu loop                                      */
  875.  
  876.                     /* menIsNew:                                      */
  877.                     /*   1 - user has choosen another menu            */
  878.                     /*   0 - show the same menu again                 */
  879.   menuIsNew = 1
  880.  
  881.  
  882.   do forever
  883.                     /* default entries used if after processing the   */
  884.                     /* OnInit command !curRc is not equal ''          */
  885.     !NextMenu = '0001'x
  886.     !Backlevel = 1
  887.  
  888.                     /* save the name of the current menu              */
  889.  
  890.                     /* execute the OnInit statements if any exist     */
  891.     call I!.__ILine '?',, menu.!thisMenu.__OnInit
  892.  
  893.                     /* check the return code                          */
  894.     if !curRC = '' then
  895.     do
  896.       !NextMenu = ''
  897.  
  898.                     /* show the listbox                               */
  899.       ListBoxResult = I!.__ShowListBox( menuIsNew )
  900.     end /* if !curRC = '' then */
  901.  
  902.                     /* execute the OnExit statements if any exist     */
  903.     call I!.__ILine '?',, menu.!thisMenu.__OnExit
  904.  
  905.                     /* check the return code                          */
  906.     if !curRC <> '' then
  907.       iterate       /* error: show the same menu again                */
  908.  
  909.     menuIsNew = 1
  910.  
  911.                     /* check the result of I!.__ShowListBox           */
  912.     select
  913.  
  914.       when !NextMenu = '0001'x then
  915.       do
  916.                     /* go one or more menu levels back                */
  917.  
  918.                     /* check the no. of menu levels to go back        */
  919.         if datatype( !BackLevel ) <> 'NUM' then
  920.           !BackLevel = 1    /* if !Backlevel is invalid go back one   */
  921.                             /* menu                                   */
  922.  
  923.                     /* handle the special menus correct               */
  924.         if menu.__special.!thisMenu <> 1 then
  925.         do
  926.                     /* user defined menu                              */
  927.  
  928.                     /* if !Backlevel = -2, go one level back if there */
  929.                     /* are at least 2 menus on the menu stack         */
  930. /*
  931.           if !Backlevel = -2 & MenuStack.0 > 1 then
  932.             !Backlevel = 1
  933. */
  934.  
  935.           if !backlevel = -2 then
  936.             if MenuStack.0 > 1 then
  937.               !Backlevel = 1
  938.             else
  939.             do
  940.               menuIsNew = 0
  941.               !backLevel = 0
  942.             end /* else */
  943.  
  944.  
  945.                     /* if !Backlevel = -1, go back to the first menu  */
  946.           i = 1
  947.           if !Backlevel >= 0 then
  948.             i = MenuStack.0 - !BackLevel
  949.  
  950.           if i <= 0 then
  951.             leave   /* exit the program                               */
  952.  
  953.         end /* if */
  954.         else
  955.           i = MenuStack.0
  956.  
  957.         !thisMenu = MenuStack.i
  958.         MenuStack.0 = i
  959.  
  960.       end /* when */
  961.  
  962.       when !NextMenu = '' then
  963.       do
  964.                     /* it's all done - leave the program              */
  965.         global.__rc = ListBoxResult
  966.         leave
  967.       end /* when */
  968.  
  969.       otherwise
  970.       do
  971.                     /* we should call another menu                    */
  972.         menuIsNew = 0
  973.  
  974.                     /* check if the menu exist & is not empty         */
  975.         select
  976.  
  977.                     /* menu exist?                                    */
  978.           when  Menu.!NextMenu.__NoOfEntries = '' then
  979.             call I!.__ShowErrorMessage 8, !NextMenu
  980.  
  981.                     /* menu not empty?                                */
  982.           when  Menu.!NextMenu.__NoOfEntries <= 0 then
  983.             call I!.__ShowErrorMessage 9, !NextMenu
  984.  
  985.           otherwise
  986.           do
  987.                     /* menu is okay                                   */
  988.                     /* check, if the new menu is the same menu than   */
  989.                     /* the current menu                               */
  990.             if !thisMenu <> !NextMenu then
  991.             do
  992.               !thisMenu = !NextMenu
  993.  
  994.               if menu.__special.!thisMenu <> 1 then
  995.               do
  996.                     /* the new menu is a user defined menu            */
  997.                     /* -> save the menu in the menu stack             */
  998.                 i = menuStack.0
  999.                 if menuStack.i <> !thisMenu then
  1000.                 do
  1001.                   i = i +1
  1002.                   menuStack.i = !thisMenu
  1003.                   menuStack.0 = i
  1004.                 end /* if */
  1005.               end /* if menu.__special.!thisMenu <> 1 then */
  1006.  
  1007.                     /* set the marker for a new menu                  */
  1008.               menuIsNew = 1
  1009.             end /* if */
  1010.  
  1011.           end /* otherwise */
  1012.  
  1013.         end /* select */
  1014.  
  1015.       end /* otherwise */
  1016.  
  1017.     end /* select */
  1018.  
  1019.   end /* do forever */
  1020.  
  1021.  
  1022. /* ------------------------------------------------------------------ */
  1023.                     /* execute OnMainExitCode                         */
  1024.  
  1025. I!.__RxLBoxEnd1:
  1026.   call I!.__ILine '?',, !MainExitCode
  1027.  
  1028. /* ------------------------------------------------------------------ */
  1029.                     /* exit point of the routine in ALL cases         */
  1030.  
  1031. I!.__RxLBoxEnd:
  1032.                     /* house keeping                                  */
  1033.  
  1034.                     /* clear the screen if necessary                  */
  1035.   if Global.__CLS <> '' then
  1036.     call I!.__Cls Global.__CLS
  1037.  
  1038.                     /* restore the ADDRESS environment if necessary   */
  1039.   if global.__OldEnv <> address() then
  1040.     address global.__OldEnv
  1041.  
  1042.                     /* restore ANSI status if necessary               */
  1043.   if Global.__AnsiStatusChanged = 1 then
  1044.     call I!.__ResetAnsiStatus
  1045.  
  1046.   if Global.__iDeviceIsQueue = 1 then
  1047.   do
  1048.                     /* flush the current queue                        */
  1049.     do while queued() <> 0
  1050.       parse pull
  1051.     end /* do while queued() <> 0 */
  1052.  
  1053.                     /* restore the queue if necessary                 */
  1054.     if global.__OldQ <> '' then
  1055.       if RxQueue( 'G' ) <> global.__OldQ then
  1056.         call RxQueue 'S', global.__OldQ
  1057.  
  1058.   end /* if RxQueue( 'G' ) <> global.__OldQ */
  1059.   else
  1060.     if Global.__iDevice <> '' then
  1061.     do
  1062.                     /* close the input file                           */
  1063. /* ???
  1064.       signal off notready
  1065. */
  1066.       call stream Global.__iDevice, 'c', 'CLOSE'
  1067.     end /* if Global.__iDevice <> '' then */
  1068.  
  1069.   if Global.__cType <> 'COMMAND' then
  1070.     exit global.__rc
  1071.  
  1072.                     /* the next statements are only executed if       */
  1073.                     /* RxLBox was called from the command line        */
  1074.                     /* (-> if Global.__cType = 'COMMAND')             */
  1075.   if word( global.__rc,1 ) <> 'ERROR:' then
  1076.     exit 0
  1077.  
  1078.                     /* the next statements are only executed in case  */
  1079.                     /* of an error                                    */
  1080.   call LineOut 'STDERR:', ascii.__CRLF || ,
  1081.                           Global.__ProgName ,
  1082.                           ascii.__CRLF || ,
  1083.                           '  ' || global.__rc
  1084. exit 255
  1085.  
  1086. /* ------------------------------------------------------------------ */
  1087.  
  1088. /* ------------------------------------------------------------------ */
  1089. /* function: wait for a key from the standard input                   */
  1090. /*                                                                    */
  1091. /* call      call WaitForAKey {ShowPrompt}                            */
  1092. /*                                                                    */
  1093. /* where:    ShowPrompt - if 1 WaitForAKey shows the default prompt   */
  1094. /*                        message of the PAUSE command                */
  1095. /*                                                                    */
  1096. /* returns:  -                                                        */
  1097. /*                                                                    */
  1098. /* Note:     This is an exported routine!                             */
  1099. /*                                                                    */
  1100. /*           You can not use global variables in this routine         */
  1101. /*           because they are not available if called from within     */
  1102. /*           the menu descriptions!                                   */
  1103. /*                                                                    */
  1104. WaitForAKey: PROCEDURE expose (exposeList) menuDesc.__NoHalt
  1105.  
  1106.   SIGNAL OFF ERROR
  1107.  
  1108.   if arg( 1 ) = '1' then
  1109.     '@cmd /c pause'
  1110.   else
  1111.     '@cmd /c pause>NUL'
  1112.  
  1113.                     /* CTRL-C pressed                                 */
  1114.   if rc = 255 then
  1115.     call halt
  1116. return ''
  1117.  
  1118.  
  1119. /* ------------------------------------------------------------------ */
  1120. /* error handler                                                      */
  1121.  
  1122. Halt:
  1123.   if symbol( 'MENU.__CTRLCPRESSED' ) = 'VAR' then
  1124.   do
  1125.                     /* CTRL-C to abort the program is only possible   */
  1126.                     /* while RxLBox is active - not while executing   */
  1127.                     /* REXX code from the menu definition file!       */
  1128.     menu.__CtrlCPressed = 1
  1129.  
  1130.     if MenuDesc.__NoHalt <> '' then
  1131.       return
  1132.  
  1133.     global.__rc = 'WARNING: 2'
  1134.     signal I!.__RxLBoxEnd
  1135.   end /* if */
  1136.  
  1137. Halt1:
  1138.   return
  1139.  
  1140. Failure:
  1141. Error:
  1142. Syntax:
  1143. NoValue:
  1144.   call I!.__AbortProgram 99, condition('C'), sigl, rc, ', condition(D) =' condition( 'D' )
  1145.  
  1146. exit
  1147.  
  1148. /* ------------------------------------------------------------------ */
  1149. /* function: set or get an environment variable                       */
  1150. /*                                                                    */
  1151. /* call      curEnvValue = EnvValue( envVar {, newEnvValue } )        */
  1152. /*                                                                    */
  1153. /* returns:  current value of the environment variable                */
  1154. /*                                                                    */
  1155. /* Note:     This is an exported routine!                             */
  1156. /*                                                                    */
  1157. /*           You can not use global variables in this routine         */
  1158. /*           because they are not available if called from within     */
  1159. /*           the menu descriptions!                                   */
  1160. /*                                                                    */
  1161. EnvValue: PROCEDURE
  1162.   parse arg e1, e2
  1163.  
  1164.   if arg( 2, 'E' ) then
  1165.     return value( e1, e2, 'OS2ENVIRONMENT' )
  1166.   else
  1167.     return value( e1, , 'OS2ENVIRONMENT' )
  1168.  
  1169. /* ------------------------------------------------------------------ */
  1170. /* function: Show working message                                     */
  1171. /*                                                                    */
  1172. /* call:     ShowWorkingMessage message {, wait } {, noCls }          */
  1173. /*                                                                    */
  1174. /* where:    message - message to show                                */
  1175. /*           wait - if 1 wait for a key else not                      */
  1176. /*                  (def.: do not wait for a key)                     */
  1177. /*           noCls - do not clear the screen before displaying the    */
  1178. /*                   message if this parameter is set to 0            */
  1179. /*                   (def.: clear the screen)                         */
  1180. /*                                                                    */
  1181. /* returns:  -                                                        */
  1182. /*                                                                    */
  1183. /* Note:     This is an exported routine!                             */
  1184. /*                                                                    */
  1185. /*           You can not use global variables in this routine         */
  1186. /*           because they are not available if called from within     */
  1187. /*           the menu descriptions!                                   */
  1188. /*                                                                    */
  1189. ShowWorkingMessage: PROCEDURE expose (exposeList) menuDesc.__NoHalt
  1190.   if Global.__Quiet = 1 then
  1191.     return
  1192.  
  1193.   parse arg wrkMsg +76, qMode, qCls
  1194.  
  1195.   l = length( wrkMsg )
  1196.  
  1197.   s1 = copies( '─', l+2 )
  1198.  
  1199.   sESC = '1B'x || '['
  1200.  
  1201.   if qCls <> 0 then
  1202.     call CharOut , sESC || '1;1H' || sESC || '2J'
  1203.  
  1204.   call CharOut, ,
  1205.       sESC || '36;40;1;m' || ,
  1206.       sESC || '10;' || (76-l) % 2 || ';H┌'  || s1         ||  '┐' || ,
  1207.       sESC || '11;' || (76-l) % 2 || ';H│ ' || wrkMsg     || ' │' || ,
  1208.       sESC || '12;' || (76-l) % 2 || ';H└'  || s1         ||  '┘' || ,
  1209.       sESC || '0;m'
  1210.  
  1211.   if qMode = 1 then
  1212.     call WaitForAKey
  1213.  
  1214. RETURN ''
  1215.  
  1216. /* ------------------------------------------------------------------ */
  1217. /* function: Process the lines from the inputchannel                  */
  1218. /*                                                                    */
  1219. /* call:     I!.__CreateMenues                                        */
  1220. /*                                                                    */
  1221. /* returns:  a list of all found menus as string separated with       */
  1222. /*           null bytes ('00'x)                                       */
  1223. /*                                                                    */
  1224. /*                                                                    */
  1225. I!.__CreateMenues: PROCEDURE expose (exposeList)
  1226.  
  1227.   inputLineIndex = 1
  1228.   menuNames = '00'x
  1229.  
  1230. /* --------------------------- */
  1231.                     /* init the menu with the default values          */
  1232.   call I!.__InitDefaultMenuEntry
  1233.  
  1234. /* --------------------------- */
  1235.                     /* init the stem for the menu list                */
  1236.  
  1237.                     /* init the menu descriptions                     */
  1238.   call I!.__InitMenuEntry !ListMenu
  1239.  
  1240.   menu.!ListMenu.__Title1 =            I!.__GetMessage( 110 )
  1241.   menu.!ListMenu.__Title2 =            Global.__iDevice
  1242.   menu.!ListMenu.__Title3 =            ''
  1243.   menu.!ListMenu.__StatusLine =        I!.__GetMessage( 111 )
  1244.   menu.!ListMenu.__InputPrompt =       I!.__GetMessage( 112 )
  1245.   menu.!ListMenu.__ErrorPrompt =       I!.__GetMessage( 113 )
  1246.   menu.!ListMenu.__HelpForF1 =         'MENULISTONLINEHELP'
  1247.   menu.!ListMenu.__HelpForALT_F1 =     'INTERNALMENU_INPUTLINEHELP'
  1248.   menu.!ListMenu.__HelpForCTRL_F1 =    'INTERNALMENU_KEYHELP'
  1249.  
  1250. /* --------------------------- */
  1251.                     /* init the stem for the macro list               */
  1252.  
  1253.                     /* init the menu descriptions                     */
  1254.   call I!.__InitMenuEntry !MacroMenu
  1255.  
  1256.   menu.!MacroMenu.__Title1 =            I!.__GetMessage( 114 )
  1257.   menu.!MacroMenu.__Title2 =            Global.__iDevice
  1258.   menu.!MacroMenu.__Title3 =            ''
  1259.   menu.!MacroMenu.__StatusLine =        I!.__GetMessage( 117 )
  1260.   menu.!MacroMenu.__InputPrompt =       I!.__GetMessage( 112 )
  1261.   menu.!MacroMenu.__ErrorPrompt =       I!.__GetMessage( 113 )
  1262.   menu.!MacroMenu.__HelpForF1 =         'MACROLISTONLINEHELP'
  1263.   menu.!MacroMenu.__HelpForALT_F1 =     'INTERNALMENU_INPUTLINEHELP'
  1264.   menu.!MacroMenu.__HelpForCTRL_F1 =    'INTERNALMENU_KEYHELP'
  1265.  
  1266. /* --------------------------- */
  1267.  
  1268.   do until InputLineIndex > inputLines.0
  1269.  
  1270.     parse upper var inputLines.InputLineIndex nextLine
  1271.     inputLineIndex = inputLineIndex + 1
  1272.  
  1273.  
  1274.                     /* split the line into firstChar, LastChar and   */
  1275.                     /* the chars between                             */
  1276.     parse var nextline sChar1 +1 1 sChar1 +2 . '' -2 sChar2 1 (sChar1) sSection (sChar2)
  1277.     sSection = strip( sSection )
  1278.  
  1279.                     /* ignore comments, empty lines and invalid      */
  1280.                     /* sections                                      */
  1281.  
  1282.     if nextLine sSection = '' | sChar1 = ';' then
  1283.       iterate
  1284.  
  1285.                     /* check for the start of the next section        */
  1286.     if nextLine  = '[MACROLIST]' then
  1287.     do
  1288.                     /* section with macro definitions found           */
  1289.       inputLineIndex = I!.__ReadMacros( inputLineIndex )
  1290.       iterate
  1291.     end /* if */
  1292.  
  1293.                     /* check for online help sections                 */
  1294.     if sChar1 || sChar2 = '[<>]' then
  1295.     do
  1296.                     /* help section found                             */
  1297.  
  1298.                     /* check for duplicate definitions                */
  1299.       if help.sSection.0 <> '' then
  1300.         call I!.__AbortProgram 18, inputLineIndex-1, sSection
  1301.  
  1302.                     /* create the stem entry for the online help      */
  1303.       inputLineIndex = I!.__CreateOnlineHelp( inputLineIndex, sSection )
  1304.  
  1305.       iterate
  1306.  
  1307.     end /* if */
  1308.  
  1309.                     /* check for menu sections                        */
  1310.     if sChar1 || sChar2 = '[**]' then
  1311.     do
  1312.                     /* menu entry found                               */
  1313.  
  1314.                     /* check the first char of the menu name for      */
  1315.                     /* invalid characters                             */
  1316.       if pos( left( sSection,1 ), '!_' ) <> 0 then
  1317.         call I!.__AbortProgram 20, inputLineIndex-1
  1318.  
  1319.                     /* check for duplicate menu sections              */
  1320.       if menu.sSection.__LastLine = '' then
  1321.       do
  1322.                     /* new menu, create the menu entry                */
  1323.         menuNames = menuNames || sSection || '00'x
  1324.  
  1325.                     /* add the menu to the menu list                  */
  1326.         i = menu.!ListMenu.__NoOfEntries + 1
  1327.         menu.!ListMenu.i.__Entry = sSection
  1328.         menu.!ListMenu.i.__Action = '#GotoMenu() ' sSection
  1329.         menu.!ListMenu.__NoOfEntries = i
  1330.       end /* else */
  1331.       else          /* duplicate menu definition                      */
  1332.         if sSection <> !defaultMenu then
  1333.           call I!.__AbortProgram 10, inputLineIndex-1, sSection
  1334.  
  1335.                     /* create the stem entry for the menu             */
  1336.       inputLineIndex = I!.__CreateMenu( inputLineIndex, sSection )
  1337.  
  1338.     end /* if */
  1339.  
  1340.   end /* do until InputLineIndex > inputLines.0 */
  1341.  
  1342.                     /* convert the colors of the default menu to      */
  1343.                     /* ANSI ESC sequences                             */
  1344.   call I!.__ConvertColorStrings !defaultMenu
  1345.  
  1346.                     /* copy the default colors to the internal menus  */
  1347.   call I!.__InitMenuEntry !ListMenu, 1
  1348.   call I!.__InitMenuEntry !MacroMenu, 1
  1349.  
  1350.                     /* ???                                            */
  1351.   drop InputLines.
  1352. RETURN menuNames
  1353.  
  1354. /* ------------------------------------------------------------------ */
  1355. /* Function: Create a menu                                            */
  1356. /*                                                                    */
  1357. /* Usage:    I!.__CreateMenu inputLineIndex, curMenuName              */
  1358. /*                                                                    */
  1359. /* where:    inputLineIndex - index for the stem inputLines.          */
  1360. /*           curMenuName - name of the menu                           */
  1361. /*                                                                    */
  1362. /* Returns:  the index of the next line in the stem inputLines.       */
  1363. /*                                                                    */
  1364. I!.__CreateMenu: PROCEDURE expose (exposeList)
  1365.   parse arg inputLineIndex , curMenuName
  1366.  
  1367.                     /* init the menu description                      */
  1368.   call I!.__InitMenuEntry curMenuName
  1369.  
  1370.   MenuItemFound = 0
  1371.  
  1372.   do curLineNo = inputLineIndex to inputLines.0
  1373.  
  1374.                     /* get the next line                              */
  1375.     curLine = inputLines.curLineNo
  1376.  
  1377.                     /* check for section starts                       */
  1378.     parse var curLine s1 +1 '' -1 s2
  1379.  
  1380.                     /* ignore comments and empty lines                */
  1381.     if curLine = '' | s1 = ';' then
  1382.       iterate
  1383.  
  1384.     if s1 || s2 = '[]' then
  1385.     do
  1386.                     /* start of next section found                    */
  1387.       inputLineIndex = curLineNo
  1388.       leave
  1389.     end /* if left( ... */
  1390.  
  1391.                     /* split the line into keyword and keyvalue       */
  1392.     parse var curLine keyword '=' keyvalue
  1393.  
  1394.                     /* translate keyword to uppercase and split the   */
  1395.                     /* keyword also into subKeyword and itemNo        */
  1396.                     /* (subKeyword and itemNo are only used for the   */
  1397.                     /* keywords MENUITEM and ACTION)                  */
  1398.     keyword = strip( keyword )
  1399.     parse upper var keyword keyword 1 subKeyword '.' itemNo 1 pmKey +3
  1400.  
  1401.                     /* ignore entries for the PM version              */   
  1402.     if PMKey = 'PM_' then
  1403.       iterate
  1404.  
  1405.     itemNo = strip( itemNo )
  1406.     itemNoType = datatype( itemNo, 'NUM' )
  1407.  
  1408.                     /* empty keywords are not possible!               */
  1409.     if keyWord = '' then
  1410.       call I!.__AbortProgram 15, curLineNo
  1411.  
  1412.                     /* help variable to read/write the stem entry     */
  1413.     nKeyWord = '__' || keyWord
  1414.  
  1415.                     /* leading blanks for keyValues are not possible  */
  1416.     keyValue = strip( keyValue, 'L' )
  1417.  
  1418.                     /* check if the value is a REXX statement         */
  1419.     parse var KeyValue firstKeyChar +1 . '' -1 lastKeyChar
  1420.     if firstKeyChar || lastKeyChar = '()' then
  1421.       call I!.__ILine curLineNo, 'keyValue', 'keyValue = ' || keyValue
  1422.  
  1423.     select
  1424.  
  1425.       when wordPos( keyword, menu.__menuMessages ) <> 0 then
  1426.       do
  1427.  
  1428.         maxLen = menu.__MenuMsgLength
  1429.         if keyword = 'INPUTPROMPT' then
  1430.           maxLen = menu.__MenuPromptLength
  1431.  
  1432.                         /* firstKeyChar = left char of keyValue       */
  1433.         if firstKeyChar <> '{' then
  1434.           menu.curMenuName.nkeyword = strip( left( keyValue, maxLen ) )
  1435.         else
  1436.           menu.curMenuName.nKeyWord = keyvalue
  1437.  
  1438.       end /* when */
  1439.  
  1440.       when wordPos( keyword, menu.__menuHelpTexts ) <> 0 then
  1441.         parse upper var keyValue menu.curMenuName.nkeyword
  1442.  
  1443.       when wordPos( keyword, menu.__menuOptions ) <> 0 then
  1444.         menu.curMenuName.nkeyword = keyValue
  1445.  
  1446.       when subKeyWord = 'MENUITEM' then
  1447.       do
  1448.         if itemNoType <> 1 then
  1449.         do
  1450.  
  1451.           if itemNo <> '#' then
  1452.             call I!.__AbortProgram 16, curLineNo
  1453.  
  1454.           itemNo = menu.curMenuName.__NoOfEntries + 1
  1455.         end /* if datatype( ... */
  1456.  
  1457.         if itemNo = 0 | menu.curMenuName.itemNo.__Entry <> '' | keyValue = '' then
  1458.           call I!.__AbortProgram 16, curLineNo
  1459.  
  1460.         if menu.curMenuName.__NoOfEntries < itemNo then
  1461.           menu.curMenuName.__NoOfEntries = itemNo
  1462.  
  1463.         if firstKeyChar <> '{' then
  1464.           menu.curMenuName.itemNo.__Entry = ,
  1465.                strip( left( keyValue, menu.__MenuMsgLength ) )
  1466.         else
  1467.           menu.curMenuName.itemNo.__Entry = keyvalue
  1468.  
  1469.       end /* when */
  1470.  
  1471.       when wordPos( subKeyWord, 'ACTION STATUSLINE' ) <> 0 then
  1472.       do
  1473.         if itemNoType <> 1 then
  1474.           if itemNo = '#' then
  1475.             itemNo = menu.curMenuName.__NoOfEntries
  1476.  
  1477.         if menu.curMenuName.itemNo.__Entry = '' then
  1478.           call I!.__AbortProgram 16, curLineNo
  1479.  
  1480.         if menu.curMenuName.__NoOfEntries < itemNo then
  1481.           menu.curMenuName.__NoOfEntries = itemNo
  1482.  
  1483.         tsubKeyWord = '__' || subKeyWord
  1484.  
  1485.         if menu.curMenuName.itemNo.tsubKeyWord <> '' then
  1486.           call I!.__AbortProgram 16, curLineNo
  1487.  
  1488.         menu.curMenuName.itemNo.tsubKeyWord = keyValue
  1489.         
  1490.       end /* when */
  1491.  
  1492.       otherwise
  1493.         call I!.__AbortProgram 7, curLineNo, inputLines.curLineNo
  1494.  
  1495.     end /* select */
  1496.  
  1497.   end /* do curLineNo = inputLineIndex to inputLines.0 */
  1498.  
  1499.                     /* convert the colors to ANSI ESC sequences       */
  1500.                     /* (only for non-default menus)                   */
  1501.   if curMenuName <> !defaultMenu then
  1502.     call I!.__ConvertColorStrings curMenuName
  1503.  
  1504. RETURN inputLineIndex
  1505.  
  1506. /* ------------------------------------------------------------------ */
  1507. /* Function: Process an online help section                           */
  1508. /*                                                                    */
  1509. /* Usage:    I!.__CreateOnlineHelp inputLineIndex, curTopic           */
  1510. /*                                                                    */
  1511. /* where:    inputLineIndex - index for the stem inputLines.          */
  1512. /*           curTopic - name of the menu where the online help is for */
  1513. /*                                                                    */
  1514. /* Returns:  the index of the next line in the stem inputLines.       */
  1515. /*                                                                    */
  1516. I!.__CreateOnlineHelp: PROCEDURE expose (exposeList)
  1517.   parse arg inputLineIndex , curTopic
  1518.  
  1519.                     /* init the description                           */
  1520.   help.CurTopic.0 = 0
  1521.  
  1522.   curHelpLineNo = 1
  1523.  
  1524.   do curLineNo = inputLineIndex to inputLines.0
  1525.  
  1526.                     /* get the next line                              */
  1527.     curLine =  inputLines.curLineNo
  1528.  
  1529.                     /* check for section starts                       */
  1530.     parse var curLine s1 +1 '' -1 s2
  1531.  
  1532.     if s1 || s2 = '[]' then
  1533.     do
  1534.                     /* start of next section found                    */
  1535.       inputLineIndex = curLineNo
  1536.       leave
  1537.     end /* if left( ... */
  1538.  
  1539.     if curHelpLineNo > menu.__EntriesPerPage then
  1540.       call I!.__AbortProgram 19, curLineNo
  1541.  
  1542.     help.CurTopic.curHelpLineNo = left( curLine , menu.__MenuMsgLength )
  1543.     curHelpLineNo = curHelpLineNo + 1
  1544.  
  1545.   end /* do curLineNo = inputLineIndex to inputLines.0 */
  1546.  
  1547.                     /* save the no. of lines for this topic           */
  1548.   help.CurTopic.0  = curHelpLineNo
  1549.  
  1550. RETURN inputLineIndex
  1551.  
  1552. /* ------------------------------------------------------------------ */
  1553. /* Function: Process a macro section                                  */
  1554. /*                                                                    */
  1555. /* Usage:    I!.__ReadMacros inputLineIndex                           */
  1556. /*                                                                    */
  1557. /* where:    inputLineIndex - index for the stem inputLines.          */
  1558. /*                                                                    */
  1559. /* Returns:  the index of the next line in the stem inputLines.       */
  1560. /*                                                                    */
  1561. I!.__ReadMacros: PROCEDURE expose (exposeList)
  1562.   parse arg inputLineIndex .
  1563.  
  1564.   do curLineNo = inputLineIndex to inputLines.0
  1565.  
  1566.                     /* get the next line                              */
  1567.     curLine = inputLines.curLineNo
  1568.  
  1569.     parse var curLine s1 +1 '' -1 s2
  1570.  
  1571.                     /* ignore empty lines and comment lines           */
  1572.     if curLine = '' | s1 = ';' then
  1573.       iterate
  1574.  
  1575.                     /* check for section starts                       */
  1576.  
  1577.     if s1 || s2 = '[]' then
  1578.     do
  1579.                     /* start of next section found                    */
  1580.       inputLineIndex = curLineNo
  1581.       leave
  1582.     end /* if left( ... */
  1583.  
  1584.                     /* split the line into keyword and keyvalue       */
  1585.     parse var curLine keyword '=' keyvalue
  1586.  
  1587.                     /* translate the keyword to uppercase and delete  */
  1588.                     /* leading and trailing blanks                    */
  1589.     parse upper var keyword keyword
  1590.     keyword = strip( keyword )
  1591.  
  1592.                     /* check for invalid lines in the macro section   */
  1593.     if keyWord = '' then
  1594.       call I!.__AbortProgram 15, curLineNo
  1595.  
  1596.     if length( keyWord ) > 25 then
  1597.       call I!.__AbortProgram 12, curLineNo
  1598.  
  1599.                     /* check for duplicate macro definitions          */
  1600.     if Menu.__Macros.0.keyWord <> '' then
  1601.       call I!.__AbortProgram 14, curLineNo, keyword
  1602.  
  1603.                     /* save the macro in the macro stem               */
  1604.     i = Menu.__Macros.0 + 1
  1605.     Menu.__Macros.i = keyWord
  1606.     Menu.__Macros.0 = i
  1607.  
  1608.                     /* check if the value is a REXX statement         */
  1609.     parse var KeyValue firstKeyChar +1 . '' -1 lastKeyChar
  1610.     if firstKeyChar || lastKeyChar = '()' then
  1611.       call I!.__ILine curLineNo, 'keyValue', 'keyValue = ' keyValue
  1612.  
  1613.                     /* add the macro to the macro menu                */
  1614.     tline = keyWord '-' keyValue
  1615.  
  1616.     if length( tLine ) > menu.__MenuLineLength-8 then
  1617.       tLine = left( tLine, menu.__MenuLineLength-8 ) '...'
  1618.  
  1619.     i = menu.!MacroMenu.__NoOfEntries + 1
  1620.     menu.!MacroMenu.i.__Entry = tLine
  1621.  
  1622.     if firstKeyChar <> '#' then
  1623.       menu.!MacroMenu.i.__Action = '#ExecuteCmd() ' keyValue
  1624.     else
  1625.       menu.!MacroMenu.i.__Action = keyValue
  1626.  
  1627.     menu.!MacroMenu.__NoOfEntries = i
  1628.  
  1629.     Menu.__Macros.0.keyWord = keyValue
  1630.  
  1631.   end /* do */
  1632.  
  1633. RETURN inputLineIndex
  1634.  
  1635. /* ------------------------------------------------------------------ */
  1636. /* Function: Init a stem for a menu                                   */
  1637. /*                                                                    */
  1638. /* Usage:    I!.__InitMenuEntry menuName                              */
  1639. /*                                                                    */
  1640. /* where:    menuName - name of the menu                              */
  1641. /*                                                                    */
  1642. /* Returns:  -                                                        */
  1643. /*                                                                    */
  1644. I!.__InitMenuEntry: PROCEDURE expose (exposeList) menuStack.
  1645.   parse arg newMenu, colorsOnly
  1646.  
  1647.                     /* init the menu descriptions                     */
  1648.   if colorsOnly = '' then
  1649.     thisEntries = menu.__menuOptions 'FKEYA1 FKEYC1 LASTLINE LASTPAGE'
  1650.   else
  1651.     thisEntries = menu.__MenuColors
  1652.  
  1653.   do i = 1 to words( thisEntries )
  1654.     cK = '__' || word( thisEntries, i )
  1655.     menu.NewMenu.ck = menu.!defaultMenu.ck
  1656.   end /* do i = 1 words( thisEntries ) */
  1657.  
  1658.   if colorsOnly = '' then
  1659.     menu.NewMenu.__NoOfEntries = 0
  1660.  
  1661. RETURN
  1662.  
  1663. /* ------------------------------------------------------------------ */
  1664. /* Function: Init the stem with the default menu values               */
  1665. /*                                                                    */
  1666. /* Usage:    I!.__InitDefaultMenuEntry                                */
  1667. /*                                                                    */
  1668. /* where:    -                                                        */
  1669. /*                                                                    */
  1670. /* Returns:  -                                                        */
  1671. /*                                                                    */
  1672. /* Notes:    This menu contains the default values for all other      */
  1673. /*           menus.                                                   */
  1674. /*           You can redefine this menu any time in the menu          */
  1675. /*           descriptions.                                            */
  1676. /*                                                                    */
  1677. I!.__InitDefaultMenuEntry: PROCEDURE expose (exposeList)
  1678.  
  1679.                     /* init the menu descriptions                     */
  1680.                     /* Note: By default all entries are '' at the     */
  1681.                     /*       time this routine is called!             */
  1682.  
  1683.   menu.!defaultMenu.__NoOfEntries =       0
  1684.   menu.!defaultMenu.__AcceptAllInput =    0
  1685.  
  1686. /*
  1687.   menu.!defaultMenu.__InputVar       =   ''
  1688. */
  1689.  
  1690.                     /* default key definitions                        */
  1691.   menu.!defaultMenu.__Fkey1  =            '#SHOWHELP()'
  1692.   menu.!defaultMenu.__FKeyA1 =            '#SHOWLINEHELP()'
  1693.   menu.!defaultMenu.__FkeyC1 =            '#SHOWKEYHELP()'
  1694.  
  1695.   menu.!defaultMenu.__ESC    =            '#GOBACK()'
  1696.  
  1697. /*
  1698.   menu.!defaultMenu.__Fkey2  =            ''
  1699. */
  1700.  
  1701.   menu.!defaultMenu.__Fkey3  =            '#REPEAT()'
  1702.  
  1703. /*
  1704.   menu.!defaultMenu.__Fkey4  =            ''
  1705.   menu.!defaultMenu.__FKey5  =            ''
  1706.   menu.!defaultMenu.__Fkey6  =            ''
  1707.   menu.!defaultMenu.__Fkey7  =            ''
  1708. */
  1709.  
  1710.   menu.!defaultMenu.__Fkey8  =            '#SHOWMACROLIST()'
  1711.   menu.!defaultMenu.__Fkey9  =            '#REFRESH()'
  1712.   menu.!defaultMenu.__Fkey10 =            '#QUIT()'
  1713.   menu.!defaultMenu.__Fkey11 =            '#SHOWMENULIST()'
  1714.   menu.!defaultMenu.__Fkey12 =            '#SHOWHISTORY()'
  1715.  
  1716.   menu.!defaultMenu.__Title1 =            I!.__GetMessage( 115, 'title1' )
  1717.   menu.!defaultMenu.__Title2 =            I!.__GetMessage( 115, 'title2' )
  1718.   menu.!defaultMenu.__Title3 =            I!.__GetMessage( 115, 'title3' )
  1719.   menu.!defaultMenu.__StatusLine =        I!.__GetMessage( 115, 'statusline')
  1720.  
  1721. /*
  1722.   menu.!defaultMenu.__HelpStatusLine =    ''
  1723. */
  1724.  
  1725.   menu.!defaultMenu.__InputPrompt =       I!.__GetMessage( 112 )
  1726.   menu.!defaultMenu.__HelpPrompt =        I!.__GetMessage( 113 )
  1727.   menu.!defaultMenu.__ErrorPrompt =       I!.__GetMessage( 113 )
  1728.  
  1729.   menu.!defaultMenu.__FrameColor =        'HIGHLIGHT GREEN ON BLACK'
  1730.   menu.!defaultMenu.__ItemColor =         'HIGHLIGHT CYAN ON BLACK'
  1731.   menu.!defaultMenu.__SelectedItemColor = 'HIGHLIGHT YELLOW ON MAGNENTA'
  1732.   menu.!defaultMenu.__Title1Color =       'HIGHLIGHT CYAN ON BLACK'
  1733.   menu.!defaultMenu.__Title2Color =       'HIGHLIGHT CYAN ON BLACK'
  1734.   menu.!defaultMenu.__Title3Color =       'BLUE ON WHITE'
  1735.   menu.!defaultMenu.__StatuslineColor =   'HIGHLIGHT YELLOW ON BLACK'
  1736.   menu.!defaultMenu.__ErrorTextColor =    'HIGHLIGHT YELLOW ON RED'
  1737.   menu.!defaultMenu.__InputLineColor =    'HIGHLIGHT YELLOW ON MAGNENTA'
  1738.   menu.!defaultMenu.__CLS =               'WHITE ON BLACK'
  1739.  
  1740. /*
  1741.   menu.!defaultMenu.__HelpForF1 =         ''
  1742.   menu.!defaultMenu.__HelpForALT_F1 =     ''
  1743.   menu.!defaultMenu.__HelpForCTRL_F1 =    ''
  1744. */
  1745.  
  1746.   menu.!defaultMenu.__LastLine =          0
  1747.   menu.!defaultMenu.__LastPage =          1
  1748. RETURN
  1749.  
  1750. /* ------------------------------------------------------------------ */
  1751. /* Function: Convert the color strings of a menu to ANSI ESC          */
  1752. /*           sequences                                                */
  1753. /*                                                                    */
  1754. /* Usage:    I!.__ConvertColorStrings menuName                        */
  1755. /*                                                                    */
  1756. /* where:    menuName - name of the menu                              */
  1757. /*                                                                    */
  1758. /* Returns:  -                                                        */
  1759. /*                                                                    */
  1760. /*                                                                    */
  1761. I!.__ConvertColorStrings: PROCEDURE expose (exposeList)
  1762.   parse arg MenuN
  1763.  
  1764.   do i = 1 to words( menu.__menuColors )
  1765.     menuV = '__' || word( menu.__menuColors,i )
  1766.  
  1767.     menu.MenuN.MenuV = I!.__GetColorString( menu.MenuN.MenuV )
  1768.   end /* do i = 1 to words( menu.__menuColors ) */
  1769.  
  1770. RETURN
  1771.  
  1772. /* ------------------------------------------------------------------ */
  1773. /* Function: Create the history menu                                  */
  1774. /*                                                                    */
  1775. /* Usage:    I!.__CreateHistoryMenu                                   */
  1776. /*                                                                    */
  1777. /* where:    -                                                        */
  1778. /*                                                                    */
  1779. /* Returns:  !HistoryMenu                                             */
  1780. /*                                                                    */
  1781. I!.__CreateHistoryMenu: PROCEDURE expose (exposeList) menuStack.
  1782.  
  1783.                     /* init the menu descriptions                     */
  1784.   call I!.__InitMenuEntry !HistoryMenu
  1785.  
  1786.   menu.!HistoryMenu.__Title1 =            I!.__GetMessage( 116 )
  1787.   menu.!HistoryMenu.__Title2 =            '(' Global.__iDevice ')'
  1788.  
  1789. /*
  1790.   menu.!HistoryMenu.__Title3 =            ''
  1791. */
  1792.  
  1793.   menu.!HistoryMenu.__StatusLine =        I!.__GetMessage( 111 )
  1794.   menu.!HistoryMenu.__InputPrompt =       I!.__GetMessage( 112 )
  1795.   menu.!HistoryMenu.__ErrorPrompt =       I!.__GetMessage( 113 )
  1796.   menu.!HistoryMenu.__HelpForF1 =         'HISTORYLISTONLINEHELP'
  1797.   menu.!HistoryMenu.__HelpForALT_F1 =     'INTERNALMENU_INPUTLINEHELP'
  1798.   menu.!HistoryMenu.__HelpForCTRL_F1 =    'INTERNALMENU_KEYHELP'
  1799.  
  1800.                     /* create an entry for each element on the menu   */
  1801.                     /* stack                                          */
  1802.   do j = 1 to MenuStack.0
  1803.                     /* add the menu to the menu list                  */
  1804.     i = menu.!HistoryMenu.__NoOfEntries + 1
  1805.     menu.!HistoryMenu.i.__Entry = MenuStack.j
  1806.     menu.!HistoryMenu.i.__Action = '#GotoMenu() ' MenuStack.j
  1807.     menu.!HistoryMenu.__NoOfEntries = i
  1808.   end /* do j = 1 to MenuStack.0 */
  1809.  
  1810. RETURN !HistoryMenu
  1811.  
  1812. /* ------------------------------------------------------------------ */
  1813. /* function: interpret a line of the menu descriptions                */
  1814. /*                                                                    */
  1815. /* call:     I!.__ILine iLineNo, gVar, lineToInterpret                */
  1816. /*                                                                    */
  1817. /* where:    iLineNo - no. of the line in the menu description        */
  1818. /*           gVar - name(s) of additional global variable(s)          */
  1819. /*           lineToInterpret - line to interpret                      */
  1820. /*                                                                    */
  1821. /* returns:  nothing                                                  */
  1822. /*                                                                    */
  1823. I!.__ILine:
  1824.   parse arg iLineNo, gVar, ILine
  1825.  
  1826.   !curCmd = UserResponse
  1827.   !curRC = ''
  1828.   gVar1 = gvar exportedREXXVariables
  1829.  
  1830.   if I!.__ILine1( iLine ) then
  1831.     if iLineNo <> '?' then
  1832.       call I!.__AbortProgram 17, iLineNo, ILine
  1833.     else
  1834.     do
  1835.       call CharOut , ansi.__ESC || '21;1H' || menu.!thismenu.__FrameColor || ,
  1836.                      ansi.__WordWrapOn || substr( Menu.__MenuMask, 20*80+1 ) || ansi.__WordWrapOff
  1837.  
  1838.       call I!.__ShowErrorMessage 118, ILine
  1839.     end /* else */
  1840. RETURN 0
  1841.  
  1842. /* ------------------------------------------------------------------ */
  1843. /* sub routine of I!.__ILine to interpret the REXX statement.         */
  1844. /* Note that this routine don't know the global variables (except     */
  1845. /* the "exported REXX variables"; see RXLBOX.MEM)                     */
  1846. /*                                                                    */
  1847. I!.__ILine1: PROCEDURE expose (gvar1) menuDesc.
  1848.  
  1849.   parse arg iLIne
  1850.  
  1851.                     /* install temporary error handler                */
  1852.   SIGNAL ON  SYNTAX    NAME I!.__IError
  1853.   SIGNAL OFF NOVALUE
  1854.  
  1855. /* ???
  1856.   SIGNAL ON  ERROR     NAME I!.__IError
  1857.   SIGNAL ON  FAILURE   NAME I!.__IError
  1858.   SIGNAL ON  NOTREADY  NAME I!.__IError
  1859. */
  1860.  
  1861.   interpret ILine
  1862.  
  1863. RETURN 0
  1864.  
  1865. I!.__IError:
  1866.  
  1867. RETURN 1
  1868.  
  1869. /* ------------------------------------------------------------------ */
  1870. /* function: Read the lines from the input channel                    */
  1871. /*                                                                    */
  1872. /* call:     I!.__ReadMenuD inputChannel                              */
  1873. /*                                                                    */
  1874. /* where:    inputChannel - name of the file or QUEUE:                */
  1875. /*                                                                    */
  1876. /* returns:  nothing                                                  */
  1877. /*                                                                    */
  1878. I!.__ReadMenuD: PROCEDURE expose (exposeList)
  1879.  
  1880.   parse upper arg inputChannel 1 qKeyWord 7 QueueName
  1881.  
  1882.   if qKeyWord = 'QUEUE:' then
  1883.   do
  1884.                     /* input channel is a REXX queue                  */
  1885.     Global.__iDeviceIsQueue = 1
  1886.  
  1887.     inputChannel = qKeyWord
  1888.  
  1889.     QueueName =  strip( QueueName )
  1890.  
  1891.     OldQueueName = rxQueue( 'G' )
  1892.  
  1893.                     /* input channel is a privat queue                */
  1894.                     /* make the input queue the current queue         */
  1895.     if QueueName <> '' then
  1896.       call rxQueue 'S', QueueName
  1897.  
  1898.                       /* check the no. of queue entries               */
  1899.     if queued() = 0 then
  1900.       call I!.__AbortProgram 6, QueueName
  1901.  
  1902.   end /* if qKeyWord = 'QUEUE:' then */
  1903.   else
  1904.   do
  1905.                     /* input channel is a file                        */
  1906.  
  1907.                     /* check if the file exist                        */
  1908.     if stream( inputChannel, 'c', 'QUERY EXIST' ) = '' then
  1909.       call I!.__AbortProgram 2, inputChannel
  1910.  
  1911.                     /* check if the file is empty or a device         */
  1912.     tcheck = stream( inputChannel, 'c', 'QUERY SIZE' )
  1913.     if tcheck = 0 | tcheck = '' then
  1914.       call I!.__AbortProgram 3, inputChannel
  1915.  
  1916.     if stream( inputChannel, 'c', 'OPEN READ' ) <> 'READY:' then
  1917.       call I!.__AbortProgram 4, inputChannel
  1918.  
  1919.                     /* read the complete file using Charin()          */
  1920.     iFile = charIN( inputChannel, 1, chars( inputChannel ) )
  1921.  
  1922.                     /* close the file                                 */
  1923.     call stream inputChannel, "c", "CLOSE"
  1924.  
  1925.                     /* split the file into lines by hand              */
  1926.     startpos = 1
  1927.  
  1928.   end /* else */
  1929.  
  1930.                     /* init the stem with the lines of the file       */
  1931.   j = 1
  1932.   k = 1
  1933.  
  1934.   do i = 1
  1935.  
  1936.     if Global.__iDeviceIsQueue = 1 then
  1937.     do
  1938.                     /* get the next line from the queue               */
  1939.       if queued() = 0 then
  1940.         leave
  1941.  
  1942.       curLine = lineIN( 'QUEUE:' )
  1943.     end /* if Global.__iDeviceIsQueue = 1 then */
  1944.     else
  1945.     do
  1946.                     /* get the next line from the file                */
  1947.       curpos = pos( '0D0A'x, iFile, startpos )
  1948.       if curpos = 0 then
  1949.         leave
  1950.  
  1951.       lineLen = ( curpos - startpos )
  1952.  
  1953.       curLine = substr( iFile, startpos, linelen )
  1954.  
  1955.       startpos = curpos + 2
  1956.  
  1957.     end /* else */
  1958.  
  1959.     curLine = strip( curLine )
  1960.  
  1961.     parse var inputLines.j '' -1 _1endChar '' -2 _2endChars
  1962.  
  1963.     select
  1964.  
  1965.       when curLine = '' then
  1966.         iterate
  1967.  
  1968.       when _1endChar <> '\' then
  1969.         j = i
  1970.  
  1971.       when _2endChars = '^\' then
  1972.       do
  1973.         inputLines.j = dbrright( inputLines.j, 2 ) || '\'
  1974.         j = i
  1975.       end /* when */
  1976.  
  1977.       otherwise
  1978.         inputLines.j = dbrright( inputLines.j, 1 )
  1979.  
  1980.     end /* select */
  1981.  
  1982.     inputLines.j = inputLines.j || curLine
  1983.   end /* do forever */
  1984.  
  1985.                     /* save the no. of lines                          */
  1986.   inputLines.0 = j
  1987.  
  1988.                     /* restore the old queue                          */
  1989.   if Global.__iDeviceIsQueue = 1 & queueName <> '' then
  1990.     call rxQueue 'S', OldQueueName
  1991.   Global.__iDeviceIsQueue = 0
  1992.  
  1993. RETURN
  1994.  
  1995. /* ------------------------------------------------------------------ */
  1996. /* function: Show the listbox                                         */
  1997. /*                                                                    */
  1998. /* call:     I!.__ShowListBox curMenuName {,MenuIsNew}                */
  1999. /*                                                                    */
  2000. /* where:    menuIsNew - 1 : new menu                                 */
  2001. /*                       0 : same menu                                */
  2002. /*                       (default: 1)                                 */
  2003. /*                                                                    */
  2004. /* returns:  the value of the choosen entry                           */
  2005. /*           or "WARNING: 1" if the user aborts the menu with F10     */
  2006. /*           The global variable !NextMenu contains the name of the   */
  2007. /*           next menu if the users selects a GOTOMENU command        */
  2008. /*                                                                    */
  2009. /* input:    !thisMenu - menu to show                                 */
  2010. /*                                                                    */
  2011. I!.__ShowListBox: PROCEDURE expose (exposeList) MenuStack.
  2012.   parse arg menuIsNew
  2013.  
  2014.  
  2015.   Menu.__MenusCalled = Menu.__MenusCalled +1
  2016.  
  2017.                     /* init the return code and the variables for the */
  2018.                     /* current menu entry                             */
  2019.   parse value '' with thisRC !curMenuEntry1 !curMenuEntry !curMenuAction !curCmd
  2020.  
  2021. /* --------------------------- */
  2022.                     /* save marker to clear the screen after          */
  2023.                     /* the menu                                       */
  2024.   Global.__CLS = menu.!thisMenu.__CLS
  2025.  
  2026. /* --------------------------- */
  2027.                     /* calculate the pages                            */
  2028.   curNoOfEntries = menu.!thisMenu.__NoOfEntries
  2029.   noOfDigits = length( curNoOfEntries )
  2030.   curEntryLineLength = menu.__MenuLineLength - noOfDigits -2
  2031.  
  2032.   Pages.0 = curNoOfEntries % Menu.__EntriesPerPage + ( ( curNoOfEntries // Menu.__EntriesPerPage ) <> 0 )
  2033.  
  2034.                     /* show the menu frame only for changed or        */
  2035.                     /* new menus                                      */
  2036.   if MenuIsNew = 1 then
  2037.     call I!.__DisplayEmptyFrame
  2038.  
  2039.   do i = 1 to pages.0
  2040.     pages.i.low = ( (i-1) * Menu.__EntriesPerPage ) + 1
  2041.     pages.i.high = min( i * Menu.__EntriesPerPage, curNoOfEntries )
  2042.   end /* do i = 1 to pages.0 */
  2043.  
  2044.   curPageIndex = 1
  2045.   curCursorLine = 0
  2046.  
  2047.                     /* use previous menu entry if possible            */
  2048.   if menu.!thisMenu.__LastLine <= curNoOfEntries then
  2049.     curCursorLine = menu.!thisMenu.__LastLine
  2050.  
  2051.   if menu.!thisMenu.__LastPage <= pages.0 then
  2052.     curPageIndex = menu.!thisMenu.__LastPage
  2053.  
  2054.   response = ''
  2055.   lastCursorLine = -1
  2056.  
  2057.   do until MenuOK = 1
  2058.     MenuOK = 0
  2059.  
  2060.  
  2061.     lineNo = Menu.__FirstMenuLine
  2062.   
  2063.     do i = pages.curPageIndex.low to pages.curPageIndex.low + Menu.__EntriesPerPage-1
  2064.  
  2065.       if i <= pages.curPageIndex.high then
  2066.         call CharOut , ansi.__ESC || lineNo || ';3H' ||,
  2067.                        menu.!thisMenu.__ItemColor || ,
  2068.                        format( i, noOfDigits+1 )  || ' : ' || ,
  2069.                        left( I!.__EvaluateString( curEntryLineLength, menu.!thisMenu.i.__Entry ), curEntryLineLength )
  2070.       else
  2071.         call charOut , ansi.__ESC || lineNo || ';1H' || menu.!thisMenu.__FrameColor || menu.__emptyLine
  2072.  
  2073.       lineNo = lineNo + 1
  2074.     end /* do i = ...*/
  2075.  
  2076.                     /* no. of entries on this page -1                 */
  2077.     noOfPageEntries = pages.curPageIndex.High - pages.CurPageIndex.Low
  2078.  
  2079.     numberUsed = 0
  2080.  
  2081.     do forever
  2082.       curI = pages.curPageIndex.low + curCursorLine
  2083.  
  2084.                     /* set the exported REXX variables                */
  2085.  
  2086.       !curMenuEntry = menu.!thisMenu.curI.__Entry
  2087.       !curMenuEntry1 = strip( left( I!.__EvaluateString( curEntryLineLength, menu.!thisMenu.CurI.__Entry ), curEntryLineLength ) )
  2088.  
  2089.       !curMenuAction = menu.!thisMenu.curI.__Action
  2090.  
  2091.       !curPageNo = curPageIndex
  2092.       !curLineNo = curCursorLine+1
  2093.       !curEntryNo = curI
  2094.  
  2095.       !curPageNo = curPageIndex
  2096.       !curLineNo = curCursorLine+1
  2097.       !totalPageCount = pages.0
  2098.       !totalEntryCount = curNoOfEntries
  2099.       !curMenu = !thisMenu
  2100.       !curMainMenu = menuStack.1
  2101.  
  2102.                     /* update the messages in the mask                */
  2103.       call I!.__DisplayEmptyFrame1
  2104.  
  2105.                     /* save the current action                        */
  2106.       curMenuActionLine = !curMenuAction
  2107.  
  2108.                     /* create the user prompt                         */
  2109.       curMessage = I!.__EvaluateString( menu.__MenuPromptLength, menu.!thisMenu.__InputPrompt ) || ,
  2110.                    ' (ALT-F4: quit'
  2111.  
  2112.                     /* add the possible keystrokes to the prompt      */
  2113.       if pages.curPageIndex.low + curCursorLine <> 1 then
  2114.         curMessage = curMessage  || ', ' || Menu.__CUpKey
  2115.       if pages.curPageIndex.low + curCursorLine <> curNoOfEntries then
  2116.         curMessage = curMessage || ', ' || Menu.__CDownKey
  2117.  
  2118.       if curPageIndex < pages.0 then
  2119.         curMessage = curMessage || ', ' || menu.__PageDownKey
  2120.       if curPageIndex > 1 then
  2121.         curMessage = curMessage || ', ' || menu.__PageUpKey
  2122.  
  2123.       if menu.!thisMenu.__InputVAR = '' then
  2124.         curMessage = curMessage || ', ' || ,
  2125.                      pages.curPageIndex.Low || '...' || ,
  2126.                      pages.curPageIndex.High || '): '
  2127.       else
  2128.         curMessage = curMessage || '): '
  2129.  
  2130.       if lastCursorLine <> curCursorLine then
  2131.       do
  2132.         if lastCursorLine <> -1 then
  2133.         do
  2134.  
  2135.                       /* unmark the previous selected line              */
  2136.           i = pages.curPageIndex.low + lastCursorLine
  2137.           call CharOut , ansi.__ESC || ,
  2138.                Menu.__FirstMenuLine + lastCursorLine || ';3H' || ,
  2139.                menu.!thisMenu.__ItemColor || ,
  2140.                left( format( i, noOfDigits+1 )  || ' : ' ||,
  2141.                I!.__EvaluateString( curEntryLineLength, menu.!thisMenu.i.__Entry ) , Menu.__ScreenCols-4)
  2142.         end /* if lastCursorLine <> -1 then */
  2143.  
  2144.                       /* mark the new selected line                     */
  2145.         call CharOut , ansi.__ESC || ,
  2146.              Menu.__FirstMenuLine + curCursorLine || ';3H' || ,
  2147.              menu.!thisMenu.__SelectedItemColor || ,
  2148.              left( format( curI, noOfDigits+1 )  || ' : ' || ,
  2149.                I!.__EvaluateString( curEntryLineLength, menu.!thisMenu.curI.__Entry ), Menu.__ScreenCols-4 ) || ,
  2150.                menu.!thisMenu.__FrameColor
  2151.       end /* if */
  2152.  
  2153.       global.__StatusLine = menu.!thisMenu.curI.__StatusLine
  2154.       if global.__StatusLine = '' then
  2155.         global.__StatusLine = menu.!thisMenu.__StatusLine
  2156.  
  2157.       call I!.__DisplayStatusLine
  2158.  
  2159.       call CharOut , ansi.__ESC || '24;4H' || Menu.!thisMenu.__InputLineColor || ,
  2160.                      left( curMessage, menu.__MenuLineLength ) || ,
  2161.                      menu.!thisMenu.__FrameColor || ' ║ '  || ,
  2162.                      menu.!thisMenu.__InputLineColor  || ,
  2163.                      ansi.__ESC || '24;' || length( curMessage ) +4 || 'H'
  2164.  
  2165.                     /* get the user input                             */
  2166.       fkeyName = ''; fkeyNo = ''
  2167.       if numberUsed = 0 then
  2168.       do
  2169.         do until menu.__CtrlCPressed = 0 
  2170.                     /* close STDIN to avoid a bug in the CTRL-C       */
  2171.                     /* handling                                       */
  2172.           call stream 'STDIN', 'c', 'close'
  2173.           menu.__CtrlCPressed = 0
  2174.           UserResponse = lineIn();
  2175.                     /* close STDIN to avoid a bug in the CTRL-C       */
  2176.                     /* handling                                       */
  2177.           call stream 'STDIN', 'c', 'close'
  2178.         end /* do until() */
  2179.  
  2180.                     /* check for function keys                        */
  2181.         parse upper var UserResponse '~' fkeyName '~' 1 '~F' fkeyNo '~'
  2182.  
  2183.                     /* save all user input (except function keys) for */
  2184.                     /* the #REPEAT command                            */
  2185.         if fkeyName = '' then
  2186.           menu.__CurResponse = UserResponse
  2187.  
  2188.       end /* if numberUsed = 0 then */
  2189.  
  2190.       UserResponse = strip( UserResponse )
  2191.  
  2192.       numberUsed = 0
  2193.       returnPressed = 0
  2194.  
  2195.       call CharOut , Menu.!thisMenu.__FrameColor
  2196.  
  2197.       if UserResponse = '' then
  2198.       do
  2199.         UserResponse = curMenuActionLine
  2200.         returnPressed = 1
  2201.         if datatype( UserResponse ) = 'NUM' then
  2202.           UserResponse = '^' || UserResponse
  2203.       end /* if UserResponse = '' then */
  2204.  
  2205.                     /* check, if this is a REXX statement             */
  2206.       call I!.__EvaluateCmd 'UserResponse' , UserResponse
  2207.  
  2208.       parse upper var UserResponse UserResponseInUpperCase
  2209.  
  2210. /* --------------------------- */
  2211.                     /* check for the function keys                    */
  2212.                     /* ESC, ALTX, F1 - F12, CTRL-F1, ALT-F1           */
  2213.       if FkeyNo <> '' then
  2214.       do
  2215.  
  2216.         select
  2217.  
  2218.           when FKeyNo = 'ESC' then
  2219.             UserResponse = menu.!thisMenu.__ESC
  2220.  
  2221.           when FKeyNo = 'ALTX' then
  2222.             UserResponse = '#QUIT'
  2223.  
  2224.           otherwise
  2225.  
  2226.                     /* check for redefined function keys              */
  2227.             curKeyName = '__FKEY' || fkeyNo
  2228.             UserResponse = strip( menu.!thisMenu.curKeyName )
  2229.  
  2230.             if UserResponse = '' then
  2231.               iterate
  2232.  
  2233.         end /* select */
  2234.  
  2235.         if I!.__EvaluateCmd( 'UserResponse', UserResponse ) <> 0 then
  2236.           iterate
  2237.  
  2238.         parse var UserResponse _1char +1 UserResponse1
  2239.         if _1Char = '~' then
  2240.           UserResponse = UserResponse1
  2241.         else
  2242.           if _1Char <> '#' then
  2243.             UserResponse = '*' || UserResponse
  2244.  
  2245.         parse upper var UserResponse UserResponseInUpperCase
  2246.  
  2247.       end /* if FKeyNo <> '' then */
  2248.  
  2249. /* --------------------------- */
  2250.                     /* repeat is a special command and must come      */
  2251.                     /* first!                                         */
  2252.       if UserResponseInUpperCase = '#REPEAT()' then
  2253.       do
  2254.                     /* do not repeat the #REPEAT command!             */
  2255.         menu.__CurResponse = menu.__OldResponse
  2256.  
  2257.         if menu.__OldResponse <> '' then
  2258.         do
  2259.           UserResponse = menu.__OldResponse
  2260.           numberUsed = 1
  2261.         end /* if */
  2262.  
  2263.         iterate
  2264.       end /* if */
  2265.  
  2266. /* --------------------------- */
  2267.                     /* save the user input for the #REPEAT command    */
  2268.       menu.__OldResponse = menu.__CurResponse
  2269.  
  2270. /* --------------------------- */
  2271.                     /* check for macros                               */
  2272.       parse var UserResponseInUpperCase cMacro +25
  2273.       if Menu.__Macros.0.cMacro <> '' then
  2274.       do
  2275.  
  2276.         UserResponse = menu.__macros.0.cMacro
  2277.  
  2278.         if I!.__EvaluateCmd( 'UserResponse', UserResponse ) <> 0 then
  2279.           iterate
  2280.  
  2281.         parse var UserResponse _1char +1
  2282.         if _1Char <> '#' then
  2283.           UserResponse = '*' || UserResponse
  2284.  
  2285.         parse upper var UserResponse UserResponseInUpperCase
  2286.       end /* if ... */
  2287.  
  2288. /* --------------------------- */
  2289.  
  2290.                     /* parse the command into name, options           */
  2291.                     /* and parameters                                 */
  2292.       parse var UserResponse _1char +1 RxLBox_CMD '(' rxlbox_opt ')' rxlbox_parm
  2293.  
  2294.       if _1Char = '#' then
  2295.       do
  2296.                     /* process RxLBox commands                        */
  2297.  
  2298.        parse upper var RxLBox_CMD RxLBox_CMD
  2299.        parse upper var rxlbox_opt rxlbox_opt
  2300.  
  2301.        RxLBox_CMD  = strip( RxLBox_CMD )
  2302.        rxlbox_opt  = strip( rxlbox_opt )
  2303.        rxlbox_parm = strip( rxlbox_parm )
  2304.  
  2305.        if I!.__EvaluateCmd( 'rxlBox_Parm', rxlBox_Parm ) <> 0 then
  2306.          RxLBox_CMD = ''
  2307.  
  2308.                     /* check for RxLBox commands to show the          */
  2309.                     /* online help                                    */
  2310.         hFound = 1
  2311.         select
  2312.  
  2313.           when RxLBox_CMD = 'SHOWHELP' then
  2314.             curHelpTopic = menu.!thisMenu.__HelpForF1
  2315.  
  2316.           when RxLBox_CMD = 'SHOWLINEHELP' then
  2317.             curHelpTopic = menu.!thisMenu.__HelpForALT_F1
  2318.  
  2319.           when RxLBox_CMD = 'SHOWKEYHELP' then
  2320.             curHelpTopic = menu.!thisMenu.__HelpForCTRL_F1
  2321.  
  2322.           otherwise
  2323.             curHelpTopic = ''
  2324.             hFound = 0
  2325.  
  2326.         end /* select */
  2327.  
  2328.         if hFound = 1 then
  2329.         do
  2330.           if curHelpTopic <> '' then
  2331.           do
  2332.             if I!.__EvaluateCmd( 'curHelpTopic' , curHelpTopic ) = 0 &,
  2333.                Help.curHelpTopic.0 <> '' then
  2334.             do
  2335.               call I!.__ShowOnlineHelp curHelpTopic
  2336.               leave
  2337.             end /* if */
  2338.           end /* if */
  2339.  
  2340.           iterate
  2341.         end /* if */
  2342.  
  2343. /* --------------------------- */
  2344.                     /* check for further RxLBox commands              */
  2345.  
  2346.         if RxLBox_CMD = 'USERINPUT' then
  2347.         do
  2348.           if wordPos( 'BLANK_OK', RxLBox_Opt ) <> 0 then
  2349.             if pos( 'MENUDESC.', translate( rxlbox_parm ) ) = 1 then
  2350.               call I!.__ILine '?',, rxlbox_parm '= "" ' 
  2351.             else
  2352.               call value strip( rxlbox_parm ), '', 'OS2ENVIRONMENT'
  2353.           iterate
  2354.         end /* */
  2355.  
  2356.         if RxLBox_CMD = 'REXXCMD' | RxLBox_CMD = 'EXECUTECMD' then
  2357.         do
  2358.                     /* execute an OS/2 command                        */
  2359.           if RxLBox_CMD = 'EXECUTECMD' then
  2360.             call I!.__ExecuteUserCommand RxLBox_Parm,0
  2361.  
  2362.                     /* execute a REXX statement                       */
  2363.           if RxLBox_CMD = 'REXXCMD' then
  2364.             if I!.__ILine( '?',, RxLBox_Parm ) <> 0 then
  2365.               RxLBox_CMD = 'REFRESH'
  2366.  
  2367.                     /* process the options for the REXXCMD and        */
  2368.                     /* EXECUTECMD commands                            */
  2369.           select
  2370.             when wordpos( 'GOBACK', RXLBox_Opt ) <> 0 then
  2371.               RxLBox_CMD = 'GOBACK'
  2372.  
  2373.             when wordpos( 'QUIT', RXLBox_Opt ) <> 0 then
  2374.               RxLBox_CMD = 'QUIT'
  2375.  
  2376.             when wordPos( 'PAUSE', RxLBox_Opt ) <> 0 then
  2377.             do
  2378.               call WaitForAKey
  2379.               RxLBox_CMD = 'REFRESH'
  2380.             end /* when */
  2381.  
  2382.             when wordPos( 'NOP', RxLBox_Opt ) <> 0 then
  2383.               RxLBox_CMD = 'NOP'
  2384.  
  2385.             otherwise
  2386.               RxLBox_CMD = 'REFRESH'
  2387.  
  2388.           end /* select */
  2389.  
  2390.         end /* if */
  2391.  
  2392. /* --------------------------- */
  2393.  
  2394.         if RxLBox_CMD = 'REFRESH' then
  2395.         do
  2396.                     /* refresh the display                            */
  2397.           call I!.__DisplayEmptyFrame
  2398. /*
  2399.           UserResponseInUpperCase = '~HOME~'
  2400. */
  2401.           leave
  2402.         end /* if */
  2403.  
  2404. /* --------------------------- */
  2405.  
  2406.         if RxLBox_CMD = 'NOP' then
  2407.           iterate
  2408.  
  2409. /* --------------------------- */
  2410.  
  2411.         !NextMenu = ''
  2412.  
  2413.                     /* show the menu with a list of a menus called    */
  2414.                     /* so far                                         */
  2415.         if RxLBox_CMD = 'SHOWHISTORY' then
  2416.           !NextMenu = I!.__CreateHistoryMenu()
  2417.  
  2418.                     /* show the menu with all menus defined in the   */
  2419.                     /* menu descriptions                             */
  2420.         if RxLBox_CMD = 'SHOWMENULIST' then
  2421.           !NextMenu = !ListMenu
  2422.  
  2423.                     /* show the menu with a list of all macros        */
  2424.                     /* defined in the menu descriptions               */
  2425.         if RxLBox_CMD = 'SHOWMACROLIST' then
  2426.           !NextMenu = !MacroMenu
  2427.  
  2428.                     /* switch to another menu defined in the menu     */
  2429.                     /* descriptions                                   */
  2430.         if RxLBox_CMD = 'GOTOMENU' then
  2431.           parse upper var rxlbox_parm !NextMenu
  2432.  
  2433.         if RxLBox_CMD = 'GOBACK' then
  2434.         do
  2435.                     /* go one menu level back                         */
  2436.           !NextMenu = '0001'x
  2437.           !BackLevel = RxLBox_Parm
  2438.         end /* if */
  2439.  
  2440.         if RxLBox_CMD = 'QUIT' | !NextMenu <> '' then
  2441.         do
  2442.                     /* leave the program (or call another menu if the */
  2443.                     /* command was used by another command, see       */
  2444.                     /* above)                                         */
  2445.           MenuOK = 1
  2446.           thisRC = ''
  2447.           leave
  2448.         end /* if */
  2449.  
  2450.                     /* invalid command found                          */
  2451.         menuIsNew = 0
  2452.         call I!.__ShowErrorMessage 13, RxLBox_CMD
  2453.         leave
  2454.  
  2455.       end /* if RxLBox_CMD = 'QUIT' | !NextMenu <> '' then */
  2456.  
  2457. /* --------------------------- */
  2458.                     /* check for function keys                        */
  2459. /*
  2460.       parse upper var UserResponseInUpperCase '~' fKeyName '~'
  2461. */
  2462.       if fkeyName <> '' then
  2463.       do
  2464.                     /* Cursor Up                                      */
  2465.         if fKeyName = 'CUP' then
  2466.           if curCursorLine <= 0 then
  2467.             fKeyName = 'PGUP'
  2468.           else
  2469.           do
  2470.             lastCursorLine = curCursorLine
  2471.             curCursorLine = curCursorLine -1
  2472.             iterate
  2473.           end /* else */
  2474.  
  2475.                     /* Cursor Down                                    */
  2476.         if fKeyName = 'CDN' then
  2477.           if curCursorLine >= noOfPageEntries then
  2478.             fkeyName = 'PGDN'
  2479.           else
  2480.           do
  2481.             lastCursorLine = curCursorLine
  2482.             curCursorLine = curCursorLine + 1
  2483.             iterate
  2484.           end /* else */
  2485.  
  2486.                     /* PgDn                                           */
  2487.         if fkeyName = 'PGDN' then
  2488.           if curPageIndex < pages.0 then
  2489.           do
  2490.             curPageIndex = curPageIndex + 1
  2491.             lastCursorLine = -1
  2492.             curCursorLine = 0
  2493.             leave
  2494.           end /* if */
  2495.           else
  2496.             fkeyName = 'CEND'
  2497.  
  2498.                     /* PgUp                                           */
  2499.         if fkeyName = 'PGUP' then
  2500.           if curPageIndex > 1 then
  2501.           do
  2502.             curPageIndex = curPageIndex - 1
  2503.  
  2504.             lastCursorLine = -1
  2505.             curCursorLine = pages.curPageIndex.High - pages.CurPageIndex.Low
  2506.             leave
  2507.           end
  2508.           else
  2509.             fkeyName = 'CHOME'
  2510.  
  2511.                     /* Home                                           */
  2512.         if fKeyName =  'HOME' then
  2513.           if curPageIndex <> 1 then
  2514.           do
  2515.             lastCursorLine = -1
  2516.             curCursorLine = 0
  2517.             curPageIndex = 1
  2518.             leave
  2519.           end
  2520.           else
  2521.             fkeyName = 'CHOME'
  2522.  
  2523.                     /* Ctrl-Home                                      */
  2524.         if fkeyName = 'CHOME' then
  2525.         do
  2526.           if curCursorLIne = 0 then
  2527.             iterate
  2528.  
  2529.           lastCursorLine = curCursorLine
  2530.           curCursorLine = 0
  2531.           iterate
  2532.  
  2533.         end /* if */
  2534.  
  2535.                     /* End                                            */
  2536.         if fkeyName = 'END' then
  2537.           if curPageIndex <> pages.0 then
  2538.           do
  2539.             lastCursorLine = -1
  2540.             curPageIndex = pages.0
  2541.             curCursorLine = pages.curPageIndex.High - pages.CurPageIndex.Low
  2542.             leave
  2543.           end
  2544.           else
  2545.             fkeyName = 'CEND'
  2546.  
  2547.                     /* Ctrl-End                                       */
  2548.         if fkeyName = 'CEND' then
  2549.         do
  2550.           if curCursorLine = noOfPageEntries then
  2551.             iterate
  2552.  
  2553.           lastCursorLine = CurCursorLine
  2554.           curCursorLine = noOfPageEntries
  2555.           iterate
  2556.  
  2557.         end /* if */
  2558.  
  2559.       end /* if fkeyName <> '' then */
  2560.  
  2561. /* --------------------------- */
  2562.  
  2563.       parse var UserResponse _1Char +1 _userCmd
  2564.       if _1Char = '*' then
  2565.       do
  2566.                     /* OS/2 command                                   */
  2567.         call I!.__ExecuteUserCommand _userCmd
  2568.         leave
  2569.       end /* if left( ... */
  2570.  
  2571. /* --------------------------- */
  2572.  
  2573.       envVar = ''
  2574.       envValue = userResponse
  2575.  
  2576.       parse var curMenuActionLine tcurcmd '(' tcurOpt ')' tcurParm
  2577.  
  2578.       if translate( tcurCmd ) = '#USERINPUT' then
  2579.       do
  2580.         if envValue <> '' then
  2581.         do
  2582.           parse var tcurParm envVar '#' checkStmt '#' errMsg
  2583.           envVar = strip( envVar )
  2584.  
  2585.           call I!.__EvaluateCmd 'envVar', envVar
  2586.  
  2587.           if checkStmt <> '' then
  2588.           do
  2589.             tRC = 0
  2590.             call I!.__ILine '?' , 'envValue tRC', 'tRC = 'checkStmt
  2591.             if tRC = 0 then
  2592.             do
  2593.               call I!.__ShowErrorMessage 104 , I!.__EvaluateString( , errMsg )
  2594.               envVar = ''
  2595.               leave
  2596.             end /* if tRC = 0 then */
  2597.           end /* if checkStmt <> '' then */
  2598.         end /* if envValue <> '' then */
  2599.       end /* if tcurCmd = '#USERINPUT' then */
  2600.       else
  2601.         if menu.!thisMenu.__InputVAR <> '' then
  2602.           call I!.__EvaluateCmd 'envVar', menu.!thisMenu.__InputVAR
  2603.  
  2604.       if envVar <> '' then
  2605.       do
  2606.                     /* check for control chars                        */
  2607.         parse var envValue _1Char +1 envValue1
  2608.         if _1Char = '^' then
  2609.           envValue = envValue1
  2610.  
  2611.         if wordpos( 'UPPER', tcurOpt ) <> 0 then
  2612.           envValue = translate( envValue )
  2613.  
  2614.         if envVar <> '' then
  2615.           if pos( 'MENUDESC.', translate( envVar ) ) = 1 then
  2616.             call I!.__ILine '?',, envVar || '="' || envValue || '"' 
  2617.           else
  2618.             call value envVar, envValue, 'OS2ENVIRONMENT'
  2619.         else
  2620.           call CharOut, ascii.__Bel
  2621.  
  2622.         leave
  2623.       end /* if envVar <> '' then */
  2624.  
  2625. /* --------------------------- */
  2626.                 /* convert relative positions to absolute positions   */
  2627.  
  2628.       continueMenu = 0
  2629.  
  2630.       if pos( left( UserResponseInUpperCase, 1 ), '+-' ) <> 0 then
  2631.         if datatype( UserResponseInUpperCase, 'NUM' ) == 1 then
  2632.         do
  2633.           UserResponseInUpperCase = pages.curPageIndex.low + UserResponseInUpperCase + curCursorLine
  2634.           ContinueMenu = 1
  2635.         end /* if */
  2636.  
  2637.       if datatype( UserResponseInUpperCase, 'NUM' ) == 1 then
  2638.       do
  2639.         if UserResponseInUpperCase >= pages.curPageIndex.low & ,
  2640.            UserResponseInUpperCase <= pages.curPageIndex.high & ,
  2641.            continueMenu <> 1 then
  2642.         do
  2643.                 /* position is on this page - end the program         */
  2644.                 /* if the action is not empty                         */
  2645.  
  2646.           if menu.!thisMenu.UserResponseInUpperCase.__Entry = '' then
  2647.             iterate     /* no action for this entry - continue prog.  */
  2648.  
  2649.           thisRC = I!.__EvaluateString( , menu.!thisMenu.UserResponseInUpperCase.__Action )
  2650.           if pos( left( thisRC,1 ), '#*' ) <> 0 then
  2651.           do
  2652.  
  2653.             UserResponseInUpperCase = thisRC
  2654.             userResponse = thisRC
  2655.  
  2656.             numberUsed = 1
  2657.             iterate
  2658.           end /* if */
  2659.  
  2660.                         /* the next two statements are only executed  */
  2661.                         /* if the IF statement is false               */
  2662.           MenuOK = 1
  2663.           leave
  2664.         end
  2665.         else
  2666.         do
  2667.                 /* position is on another page - show that page       */
  2668.           if UserResponseInUpperCase <= 0 then
  2669.             UserResponseInUpperCase = 1
  2670.           if UserResponseInUpperCase >= curNoOfEntries then
  2671.             UserResponseInUpperCase = curNoOfEntries
  2672.  
  2673.           lastPageIndex = curPageIndex
  2674.           lastCursorLine = curCursorLine
  2675.  
  2676.           curPageIndex = ( UserResponseInUpperCase % menu.__EntriesPerPage )
  2677.           curCursorLine = (UserResponseInUpperCase // menu.__EntriesPerPage )
  2678.           if curCursorLine <> 0 then
  2679.             curPageIndex = curPageIndex + 1
  2680.  
  2681.           if curCursorLine = 0 then
  2682.             curCursorLine = menu.__EntriesPerPage-1
  2683.           else
  2684.             curCursorLine = curCursorLine -1
  2685.  
  2686.           if lastPageIndex = curPageIndex then
  2687.             iterate
  2688.  
  2689.                         /* the next two statements are only executed  */
  2690.                         /* if the IF statement is false               */
  2691.           lastCursorLine = -1
  2692.           leave
  2693.  
  2694.         end /* else */
  2695.       end /* if datatype( UserResponseInUpperCase, 'NUM' ) == 1 then */
  2696.  
  2697. /* --------------------------- */
  2698.                     /* any other input                                */
  2699.       if menu.!thisMenu.__AcceptAllInput = 'YES' | returnPressed = 1 then
  2700.       do
  2701.         thisRC = I!.__EvaluateString( , UserResponse )
  2702.         menuOk = 1
  2703.         leave
  2704.       end /* if menu.!thisMenu.__AcceptAllInput = 'YES' then */
  2705.  
  2706.                         /* the next statement is only executed        */
  2707.                         /* if the IF statement is false               */
  2708.       call charOut, ascii.__BEL
  2709.  
  2710.     end /* do forever */
  2711.  
  2712.   end /* do until MenuOK = 1 */
  2713.  
  2714.                     /* save the current page and entry of this menu   */
  2715.   menu.!thisMenu.__LastLine = curCursorLine
  2716.   menu.!thisMenu.__LastPage = curPageIndex
  2717.  
  2718. /* --------------------------- */
  2719.                     /* check for control chars                        */
  2720.   parse var thisRC _1Char +1 thisRC1
  2721.   if _1Char = '^' then
  2722.     thisRC = thisRC1
  2723.  
  2724. /* --------------------------- */
  2725.  
  2726. RETURN thisRC
  2727.  
  2728. /* ------------------------------------------------------------------ */
  2729. /* function: Evaluate an string from the menu description             */
  2730. /*                                                                    */
  2731. /* call:     I!.__EvaluateString { maxStringLength }, lineToEval      */
  2732. /*                                                                    */
  2733. /* where:    maxStringLength - max. length for the result string      */
  2734. /*           lineToEval - string to evaluate                          */
  2735. /*                                                                    */
  2736. /*                                                                    */
  2737. /* returns:  -                                                        */
  2738. /*                                                                    */
  2739. I!.__EvaluateString: PROCEDURE expose (exposeList)
  2740.   parse arg mLen , tStr
  2741.  
  2742.   call I!.__EvaluateCmd 'tStr', tStr
  2743.  
  2744. /*
  2745.   if mLen <> '' then
  2746.     if length( tStr ) > mLen then
  2747.       tStr = left( tStr, mLen )
  2748. */
  2749.  
  2750.  mlen = 0 || mlen
  2751.  parse var tStr +(mLen)
  2752.  
  2753. RETURN tStr
  2754.  
  2755. /* ------------------------------------------------------------------ */
  2756. /* function: Evaluate a command before executing if necessary         */
  2757. /*                                                                    */
  2758. /* call:     I!.__EvaluateCmd varName, lineToEval                     */
  2759. /*                                                                    */
  2760. /* where:    varName - name of the variable for the result            */
  2761. /*           lineToEval - string to evaluate                          */
  2762. /*                                                                    */
  2763. /* returns:  0 - ok                                                   */
  2764. /*           else error                                               */
  2765. /*                                                                    */
  2766. I!.__EvaluateCmd:
  2767.   parse arg rx.__varN . , rx.__VarV, rx.__chkCmd
  2768.  
  2769.   tRC = 0
  2770.   rx.__VarV = strip( rx.__VarV )
  2771.  
  2772.   parse var rx.__VarV s1 +1 . '' -1 s2 1 (s1) rx.__VarV1 (s2)
  2773.   if s1 || s2 = '{}' then
  2774.     tRC = ( I!.__ILine( '?', rx.__VarN,  rx.__VarN ' = ' rx.__VarV1 ) <> 0 )
  2775.   else
  2776.     call value rx.__VarN, rx.__VarV
  2777.  
  2778.   drop rx.
  2779.  
  2780. RETURN tRC
  2781.  
  2782. /* ------------------------------------------------------------------ */
  2783. /* function: Display the empty menu frame                             */
  2784. /*                                                                    */
  2785. /* call:     I!.__DisplayEmptyFrame                                   */
  2786. /*                                                                    */
  2787. /* returns:  -                                                        */
  2788. /*                                                                    */
  2789. I!.__DisplayEmptyFrame:
  2790.  
  2791.                       /* clear the screen                             */
  2792.   call I!.__Cls menu.!thisMenu.__FrameColor
  2793.  
  2794.   call CharOut , ansi.__ESC || '1;1H' || menu.!thisMenu.__FrameColor || ,
  2795.                  ansi.__WordWrapON || Menu.__MenuMask || ansi.__WordWrapOff
  2796.  
  2797. I!.__DisplayEmptyFrame1:
  2798.   if menu.!thisMenu.__Title1 <> '' then
  2799.     call CharOut , ansi.__ESC || '2;4H' || menu.!thisMenu.__Title1Color || ,
  2800.                  center( I!.__EvaluateString( menu.__MenuMsgLength, menu.!thisMenu.__Title1 ) ,,
  2801.                  menu.__MenuMsgLength ) || ,
  2802.                  menu.!thisMenu.__FrameColor
  2803.  
  2804.   if menu.!thisMenu.__Title2 <> '' then
  2805.     call CharOut , ansi.__ESC || '3;4H' || menu.!thisMenu.__Title2Color || ,
  2806.                  center( I!.__EvaluateString( menu.__MenuMsgLength, menu.!thisMenu.__Title2 ) ,,
  2807.                  menu.__MenuMsgLength ) || ,
  2808.                  menu.!thisMenu.__FrameColor
  2809.  
  2810.   if menu.!thisMenu.__Title3 <> '' then
  2811.     call CharOut , ansi.__ESC || '5;4H' || menu.!thisMenu.__Title3Color || ,
  2812.                  center( I!.__EvaluateString( menu.__MenuMsgLength, menu.!thisMenu.__Title3 ),,
  2813.                  menu.__MenuMsgLength ) || ,
  2814.                  menu.!thisMenu.__FrameColor
  2815.  
  2816. /* no RETURN because we've to show the status line */
  2817.  
  2818. /* ------------------------------------------------------------------ */
  2819. /* function: Display the status lines                                 */
  2820. /*                                                                    */
  2821. /* call:     I!.__DisplayStatusLine                                   */
  2822. /*                                                                    */
  2823. /* returns:  -                                                        */
  2824. /*                                                                    */
  2825. /* note:     DO NOT MOVE THIS ROUTINE!!!                              */
  2826. /*                                                                    */
  2827. I!.__DisplayStatusLine:
  2828. /*
  2829.   call CharOut , ansi.__ESC || '22;4H' || menu.!thisMenu.__StatusLineColor || ,
  2830.                  center( I!.__EvaluateString( menu.__MenuMsgLength, menu.!thisMenu.__StatusLine ), menu.__MenuMsgLength ) || ,
  2831.                  menu.!thisMenu.__FrameColor
  2832. */
  2833.  
  2834.   call CharOut , ansi.__ESC || '22;4H' || menu.!thisMenu.__StatusLineColor || ,
  2835.                  center( I!.__EvaluateString( menu.__MenuMsgLength, global.__StatusLine ), menu.__MenuMsgLength ) || ,
  2836.                  menu.!thisMenu.__FrameColor
  2837.  
  2838.   call CharOut , ansi.__ESC || '24;4H' || menu.!thisMenu.__InputLineColor || ,
  2839.                  center( ' ', menu.__MenuMsgLength ) || ,
  2840.                  menu.!thisMenu.__FrameColor
  2841.  
  2842. RETURN
  2843.  
  2844. /* ------------------------------------------------------------------ */
  2845. /* function: Show an error message                                    */
  2846. /*                                                                    */
  2847. /* call:     I!.__ShowErrorMessage errorNo {, errorComment}           */
  2848. /*                                                                    */
  2849. /* where:    errorNo - number of the error                            */
  2850. /*           errorComment - additional error comment                  */
  2851. /*                                                                    */
  2852. /* returns:  -                                                        */
  2853. /*                                                                    */
  2854. I!.__ShowErrorMessage: PROCEDURE expose (exposeList)
  2855.   parse arg errorNo, errCmt
  2856.  
  2857.   if Menu.__MenusCalled = 0 then
  2858.     call I!.__DisplayEmptyFrame
  2859.  
  2860.   errorMsg = I!.__GetMessage( errorNo , errCmt )
  2861.   if length( errorMsg ) > menu.__MenuMsgLength then
  2862.     errorMsg = left( errorMsg, menu.__MenuMsgLength-5 ) '...'
  2863.  
  2864.   call CharOut , ansi.__ESC || '22;4H' || menu.!thisMenu.__ErrorTextColor || ,
  2865.                  center( errorMsg , menu.__MenuMsgLength ) || ,
  2866.                  menu.!thisMenu.__FrameColor || ascii.__bel
  2867.  
  2868.   call CharOut , ansi.__ESC || '24;4H' || menu.!thisMenu.__InputLineColor || ,
  2869.                  center( I!.__EvaluateString( menu.__MenuMsgLength, menu.!thisMenu.__ErrorPrompt ),,
  2870.                  menu.__MenuMsgLength ) || ,
  2871.                  menu.!thisMenu.__FrameColor || ' ║ '  || ,
  2872.                  menu.!thisMenu.__InputLineColor  || ,
  2873.                  menu.!thisMenu.__FrameColor
  2874.  
  2875.   call WaitForAKey
  2876.  
  2877. RETURN
  2878.  
  2879. /* ------------------------------------------------------------------ */
  2880. /* Function: Show an entry of the online help                         */
  2881. /*                                                                    */
  2882. /* Usage:    I!.__ShowOnlineHelp curTopic                             */
  2883. /*                                                                    */
  2884. /* where:    curTopic - name of the menu where the online help is for */
  2885. /*                                                                    */
  2886. /* Returns:  -                                                        */
  2887. /*                                                                    */
  2888. I!.__ShowOnlineHelp: PROCEDURE expose (exposeList)
  2889.   parse arg curTopic
  2890.  
  2891.   do i = 1 to Menu.__EntriesPerPage
  2892.     call CharOut, ansi.__ESC || i+menu.__FirstMenuLine-1 || ';3H' || ,
  2893.                   menu.!thisMenu.__StatusLineColor || ' ' || ,
  2894.                   center( strip( help.curTopic.i ) , menu.__MenuMsgLength ) || ' '
  2895.   end /* do i = 1 to Menu.__EntriesPerPage */
  2896.  
  2897.   call CharOut , ansi.__ESC || '22;4H' || menu.!thisMenu.__StatusLineColor || ,
  2898.                center( I!.__EvaluateString( menu.__MenuMsgLength, menu.!thisMenu.__HelpStatusLine ),,
  2899.                menu.__MenuMsgLength ) || ,
  2900.                menu.!thisMenu.__FrameColor
  2901.  
  2902.   call CharOut , ansi.__ESC || '24;4H' || menu.Topic.__InputLineColor || ,
  2903.                  center( I!.__EvaluateString( menu.__MenuMsgLength, menu.!thisMenu.__HelpPrompt ),,
  2904.                  menu.__MenuMsgLength ) || ,
  2905.                  menu.!thisMenu.__FrameColor || ' ║ '
  2906.  
  2907.   call WaitForAKey
  2908.  
  2909. RETURN
  2910.  
  2911. /* ------------------------------------------------------------------ */
  2912. /* function: Execute an user defined command                          */
  2913. /*                                                                    */
  2914. /* call:     I!.__ExecuteUserCommand userCommand {,displayFrame}      */
  2915. /*                                                                    */
  2916. /* where:    userCommand - command to execute                         */
  2917. /*           displayFrame - if 0 do not redisplay the frame           */
  2918. /*                          else do, default is redisplay the frame   */
  2919. /*                                                                    */
  2920. /* returns:  -                                                        */
  2921. /*                                                                    */
  2922. I!.__ExecuteUserCommand: PROCEDURE expose (exposeList)
  2923.  
  2924.   parse arg wfc +1 UserCmd, dispFrame
  2925.                      /* wfC = * -> wait after command                  */
  2926.  
  2927.   call I!.__Cls global.__cls
  2928.   call I!.__ResetAnsiStatus
  2929.  
  2930. /* ???
  2931.   SIGNAL OFF ERROR
  2932.   SIGNAL OFF FAILURE
  2933.   SIGNAL OFF NOTREADY
  2934. */
  2935.  
  2936.   SIGNAL ON SYNTAX Name  I!.__ExUserCmdExt
  2937.  
  2938.   if wfC <> '*' then
  2939.     '@cmd /c' wfc || UserCmd
  2940.   else
  2941.     '@cmd /c' UserCmd
  2942.  
  2943. I!.__ExUserCmdExt:
  2944.   SIGNAL OFF SYNTAX
  2945.  
  2946.   if wfC = '*' then
  2947.     call WaitForAKey 1
  2948.  
  2949.   call I!.__ChgAnsiStatus
  2950.  
  2951.   if dispFrame <> 0 then
  2952.     call I!.__DisplayEmptyFrame
  2953.  
  2954. RETURN
  2955.  
  2956. /* ------------------------------------------------------------------ */
  2957. /* Function: Change the ANSI status and redefine the keys             */
  2958. /*                                                                    */
  2959. /* Call:     I!.__ChgAnsiStatus                                       */
  2960. /*                                                                    */
  2961. I!.__ChgAnsiStatus: PROCEDURE expose (exposeList)
  2962.  
  2963.   Global.__AnsiStatusChanged = 1
  2964.  
  2965. /* ???
  2966.   SIGNAL OFF FAILURE
  2967.   SIGNAL OFF ERROR
  2968. */
  2969.  
  2970.                     /* turn ANSI support on                           */
  2971.   '@ANSI ON 2>NUL 1>NUL'
  2972.  
  2973.                     /* turn word wrapping off                         */
  2974.   call CharOut , ansi.__WordWrapOff
  2975.  
  2976.                     /* redefine the neccessary keys                   */
  2977.   do i = 1 to ansi.__newKeys.0
  2978.     call CharOut , ansi.__ESC || ansi.__newKeys.i.code || ,
  2979.                                  ';"~' || ansi.__newKeys.i.new || '~";13;p'
  2980.  
  2981.   end /* do i = 1 to ansi.__newKeys.0 */
  2982.  
  2983.   parse value I!.__GetDisplaySize() with cols rows
  2984.  
  2985.   if cols <> menu.__ScreenCols | rows <> menu.__ScreenRows then
  2986.   do
  2987.                     /* save the current display size and set the      */
  2988.                     /* the display size to 80x25                      */
  2989.     Global.__OldDisplaySize = cols rows
  2990.     call CharOut , ansi.__esc || '3h'
  2991.   end /* if cols <> menu.__ScreenCols | ... */
  2992.  
  2993. RETURN
  2994.  
  2995. /* ------------------------------------------------------------------ */
  2996. /* Function: Reset the ANSI status                                    */
  2997. /*                                                                    */
  2998. /* Call:     I!.__ResetAnsiStatus                                     */
  2999. /*                                                                    */
  3000. I!.__ResetAnsiStatus: PROCEDURE expose (exposeList)
  3001.  
  3002.                     /* ignore errors of external programs             */
  3003. /* ???
  3004.   SIGNAL OFF ERROR
  3005.   SIGNAL OFF FAILURE
  3006. */
  3007.  
  3008.                     /* restore the definition of the redefined        */
  3009.                     /* keys                                           */
  3010.   if symbol( "ansi.__newKeys.0" ) = 'VAR' then
  3011.     do i = 1 to ansi.__newKeys.0
  3012.       call CharOut , ansi.__ESC || ansi.__newKeys.i.code || ansi.__newKeys.i.code || ';p'
  3013.     end /* do i = 1 to ansi.__newKeys.0 */
  3014.  
  3015.                     /* turn word wrapping on                          */
  3016.                     /* and reset the display attributes               */
  3017.   call CharOut , ansi.__WordWrapOn || ansi.__AttrOff
  3018.  
  3019.                     /* restore the display size if necessary          */
  3020.   if Global.__OldDisplaySize <> '' then
  3021.     '@mode ' Global.__OldDisplaySize '2>NUL 1>NUL'
  3022.  
  3023.   Global.__AnsiStatusChanged = 0
  3024.  
  3025. RETURN
  3026.  
  3027. /* ------------------------------------------------------------------ */
  3028. /* function: convert a colorString into ANSI sequences                */
  3029. /*                                                                    */
  3030. /* call:     I!.__GetColorString colorString                          */
  3031. /*                                                                    */
  3032. /* returns:  ANSI sequences to set the colors                         */
  3033. /*                                                                    */
  3034. I!.__GetColorString: PROCEDURE expose (exposeList)
  3035.  
  3036.                     /* get the parameter                              */
  3037.   parse upper arg fgColor 'ON' bgColor
  3038.  
  3039.   if fgColor bgColor = '' then
  3040.     RETURN ''
  3041.  
  3042.                     /* init the return code                           */
  3043.   thisRC = ansi.__AttrOff
  3044.  
  3045.                     /* first round: use foreground colors             */
  3046.   cC = '__FG'
  3047.   do 2
  3048.  
  3049.     do i = 1 to words( fgColor )
  3050.       cWd = word( fgColor, i )
  3051.       thisRC = thisRC || ansi.cC.cWd || ansi.__attr.cWd
  3052.     end /* do i = 1 to words( fgColor ) */
  3053.  
  3054.                     /* second round: use background colors           */
  3055.     fgColor = bgColor
  3056.     cC = '__BG'
  3057.   end /* do 2 */
  3058.  
  3059. RETURN thisRC
  3060.  
  3061. /* ------------------------------------------------------------------ */
  3062. /* Function: Clear the screen                                         */
  3063. /*                                                                    */
  3064. /* Call:     I!.__Cls {newColor}                                      */
  3065. /*                                                                    */
  3066. /* where:    newColor - color for the screen                          */
  3067. /*                                                                    */
  3068. I!.__Cls: /* PROCEDURE expose (exposeList) */
  3069.   call CharOut , ansi.__ESC || '1;1H' || arg(1) || ansi.__ClrScr
  3070. RETURN
  3071.  
  3072. /* ------------------------------------------------------------------ */
  3073. /* function: Get the current display size                             */
  3074. /*                                                                    */
  3075. /* call:     I!.__GetDisplaySize                                      */
  3076. /*                                                                    */
  3077. /* returns:  columns rows                                             */
  3078. /*                                                                    */
  3079. /* note:     This function works only for display sizes up to 200 for */
  3080. /*           columns or rows. The upper left corner is 1,1.           */
  3081. /*           The REXXUTIL function SysCurPos uses zero based values   */
  3082. /*           (the upper left corner is 0,0).                          */
  3083. /*                                                                    */
  3084. I!.__GetDisplaySize: PROCEDURE expose (exposeList)
  3085.  
  3086.   uChars = ':;<=>?@ABCD'
  3087.  
  3088.                     /* save current cursor position                   */
  3089.   call CharOut , ansi.__ESC || '6n'
  3090.   pull curPos
  3091.  
  3092.                     /* try to set the cursor to the position 200,200  */
  3093.   call CharOut , ansi.__ESC || '200;200H'
  3094.  
  3095.                     /* get cursor position                            */
  3096.   call CharOut , ansi.__ESC || '6n'
  3097.   pull tPos
  3098.  
  3099.                     /* restore current cursor position                */
  3100.   call CharOut , left( curPos, length( curPos)-1) || 'H'
  3101.  
  3102.   parse var tPos 3 y1 +1 y2 +1 3 rows +2 6 x1 +1 x2 +1 6 cols +2 .
  3103.  
  3104.   if pos( y1, uChars ) <> 0 then
  3105.     rows = 10 || y2
  3106.  
  3107.   if pos( x1, uChars ) <> 0 then
  3108.     cols = 10 || x2
  3109.  
  3110. RETURN cols rows
  3111.  
  3112. /* ------------------------------------------------------------------ */
  3113. /* function: Create the error string and end the program              */
  3114. /*                                                                    */
  3115. /* call:     I!.__AbortProgram  errorNo {{,arg1} {...} {,arg9}}       */
  3116. /*                                                                    */
  3117. /* where:    errorNo - number of the error                            */
  3118. /*           arg1 .. arg9 - values for the placeholder in the         */
  3119. /*                          errormessages                             */
  3120. /*                                                                    */
  3121. /* returns:  nothing                                                  */
  3122. /*                                                                    */
  3123. /* Note:     This routine ends the program with a jump to the         */
  3124. /*           label RxListBoxEnd                                       */
  3125. /*                                                                    */
  3126. I!.__AbortProgram: PROCEDURE expose (exposeList)
  3127.   parse arg errorNo, a1, a2, a3, a4, a5, a6, a7, a8, a9
  3128.  
  3129.   global.__rc = I!.__GetMessage( errorNo ,,
  3130.                      a1, a2, a3, a4, a5, a6, a7, a8, a9 )
  3131.  
  3132.  
  3133. signal I!.__RxLBoxEnd
  3134.  
  3135. /* ------------------------------------------------------------------ */
  3136. /* function: Init the global menu data                                */
  3137. /*                                                                    */
  3138. /* call:     I!.__IGData                                              */
  3139. /*                                                                    */
  3140. /* returns:  -                                                        */
  3141. /*                                                                    */
  3142. I!.__IGData: /* PROCEDURE expose (exposeList) */
  3143.  
  3144.                     /* ASCII codes                                    */
  3145.   ascii.__BEL =  '07'x
  3146.   ascii.__BS  =  '08'x
  3147.   ascii.__TAB =  '09'x
  3148.   ascii.__CRLF = '0D0A'x
  3149.  
  3150. /* --------------------------- */
  3151.                     /* init the ANSI esc sequences for the            */
  3152.                     /*   - display control                            */
  3153.                     /*   - the key redefinitions                      */
  3154.                     /* and                                            */
  3155.                     /*   - the colors                                 */
  3156.   ansi.__ESC = '1B'x || '['
  3157.  
  3158.   do i = 1 to 8
  3159.  
  3160.                     /* define ANSI codes for various actions          */
  3161.     if i <= 7 then
  3162.       call value 'ANSI.__' || word( 'DELEOL CLRSCR SAVEPOS RESTPOS ATTROFF WORDWRAPOFF WORDWRAPON',i ),,
  3163.                 ansi.__ESC || word( 'K 2J s u 0;m 7l 7h', i )
  3164.  
  3165.                     /* define color attributes                        */
  3166.     if i <= 5 then
  3167.       call value 'ANSI.__ATTR.' || word( 'HIGHLIGHT NORMAL BLINK INVERS INVISIBLE', i ) ,,
  3168.                      ansi.__ESC || word( '1;m 2;m 5;m 7;m 8;m',i )
  3169.  
  3170.     cColor = word( 'BLACK RED GREEN YELLOW BLUE MAGNENTA CYAN WHITE',i )
  3171.  
  3172.                     /* define foreground color variables              */
  3173.     call value 'ANSI.__FG.' || cColor, ansi.__ESC || 29+i || ';m'
  3174.  
  3175.                     /* define background color variables              */
  3176.     call value 'ANSI.__BG.' || cColor, ansi.__ESC || 39+i || ';m'
  3177.   end /* do i = 1 to 8 */
  3178.  
  3179.                     /* create the stem with the keycodes              */
  3180.   ansi.__Newkeys.1.code = '27'              /* ESC                    */
  3181.   ansi.__Newkeys.1.new  = 'FESC'            /* go back                */
  3182.  
  3183.   keyCodes  = '45 59 94 104 60 61 62 107 63 64 65 66 67 68 133 134 71 72 73 79 80 81 118 132 119 117'
  3184.   nKeyCodes = 'FALTX F1 FC1 FA1 F2 F3 F4 FALTX F5 F6 F7 F8 F9 F10 F11 F12 HOME CUP PGUP END CDN PGDN CPGDN CPGUP CHOME CEND'
  3185.  
  3186.   do i = 2 to words( keyCodes )+1
  3187.     ansi.__NewKeys.i.code = '0;' || word( keyCodes,i-1 )
  3188.     ansi.__NewKeys.i.New = word( nKeyCodes,i-1 )
  3189.   end /* do i = 1 to words( keyCodes ) */
  3190.  
  3191.   ansi.__Newkeys.0 = 27
  3192.  
  3193. /* --------------------------- */
  3194.  
  3195.                     /* cursor key names                               */
  3196.   Menu.__CDownKey    = '19'x
  3197.   Menu.__CUpKey      = '18'x
  3198.   menu.__PageDownKey = 'PgDn'
  3199.   menu.__PageUpKey   = 'PgUp'
  3200.  
  3201.                     /* default menu description file                  */
  3202.   Global.__defMenuName = 'MAIN.MEN'
  3203.  
  3204.                     /* internal menus                                 */
  3205.                     /* Caution: The leading and trailing blanks are   */
  3206.                     /*          part of the menuname!                 */
  3207.   !ListMenu =      ' MENULIST '
  3208.   !HistoryMenu =   ' MENUHISTORY '
  3209.   !MacroMenu =     ' MACROMENU '
  3210.  
  3211.   !defaultMenu =   'DEFAULTMENU'
  3212.   !MainMenu =      'MAINMENU'
  3213.  
  3214.                     /* stem with the internal menu marker             */
  3215.   menu.__special.!HistoryMenu = 1
  3216.   menu.__special.!ListMenu = 1
  3217.   menu.__special.!MacroMenu = 1
  3218.  
  3219.                     /* function keys                                  */
  3220.   menu.__menuFKeys = ,
  3221.                 'ESC'                ,
  3222.                 'FKEY1'              ,
  3223.                 'FKEY2'              ,
  3224.                 'FKEY3'              ,
  3225.                 'FKEY4'              ,
  3226.                 'FKEY5'              ,
  3227.                 'FKEY6'              ,
  3228.                 'FKEY7'              ,
  3229.                 'FKEY8'              ,
  3230.                 'FKEY9'              ,
  3231.                 'FKEY10'             ,
  3232.                 'FKEY11'             ,
  3233.                 'FKEY12'
  3234.  
  3235.                     /* colors for the parts of the menu               */
  3236.   menu.__menuColors  = ,
  3237.                 'FRAMECOLOR'         ,
  3238.                 'ITEMCOLOR'          ,
  3239.                 'SELECTEDITEMCOLOR'  ,
  3240.                 'TITLE1COLOR'        ,
  3241.                 'TITLE2COLOR'        ,
  3242.                 'TITLE3COLOR'        ,
  3243.                 'STATUSLINECOLOR'    ,
  3244.                 'INPUTLINECOLOR'     ,
  3245.                 'ERRORTEXTCOLOR'     ,
  3246.                 'CLS'
  3247.  
  3248.                     /* messages for the menu                          */
  3249.   menu.__menuMessages = ,
  3250.                  'TITLE1'            ,
  3251.                  'TITLE2'            ,
  3252.                  'TITLE3'            ,
  3253.                  'STATUSLINE'        ,
  3254.                  'INPUTPROMPT'       ,
  3255.                  'HELPPROMPT'        ,
  3256.                  'ERRORPROMPT'       ,
  3257.                  'HELPSTATUSLINE'
  3258.  
  3259.                     /* online help sections                           */
  3260.   menu.__menuHelpTexts = ,
  3261.                  'HELPFORF1'         ,
  3262.                  'HELPFORCTRL_F1'    ,
  3263.                  'HELPFORALT_F1'
  3264.  
  3265.                     /* possible options for a menu                    */
  3266.   menu.__menuOptions = ,
  3267.                 'ACCEPTALLINPUT'     ,
  3268.                 'INPUTVAR'           ,
  3269.                 'ONINIT'             ,
  3270.                 'ONEXIT'             ,
  3271.                 'ONMAININIT'         ,
  3272.                 'ONMAINEXIT'         ,
  3273.                 menu.__menuMessages  ,
  3274.                 menu.__menuColors    ,
  3275.                 menu.__menuFKeys     ,
  3276.                 menu.__menuHelpTexts
  3277.  
  3278.   Menu.__MenusCalled = 0
  3279.  
  3280.   Menu.__Macros.0 = 0
  3281.  
  3282.   Menu.__EntriesPerPage = 14
  3283.   Menu.__FirstMenuLine = 7
  3284.  
  3285.   Menu.__ScreenCols = 80
  3286.   Menu.__ScreenRows = 25
  3287.  
  3288.   Menu.__MenuLineLength = 74
  3289.   menu.__MenuMsgLength = 74
  3290.   Menu.__MenuPromptLength = 15
  3291.  
  3292.   Menu.__emptyLine = ' ║' || copies( ' ', 76 ) || '║ '
  3293.  
  3294.   eL  = copies( '═', 76 )
  3295.   eL1 = copies( '─', 74 )
  3296.  
  3297.   Menu.__MenuMask = ,
  3298.      ' ╔'  || el                 || '╗ '  || ,
  3299.      Menu.__emptyLine                     || ,
  3300.      Menu.__emptyLine                     || ,
  3301.      ' ║ ' || el1               || ' ║ '  || ,
  3302.      Menu.__emptyLine                     || ,
  3303.      ' ╠'  || el                 || '╣ '  || ,
  3304.      copies( Menu.__emptyLine, 14 )       || ,
  3305.      ' ╠'  || el                 || '╣ '  || ,
  3306.      Menu.__emptyLine                     || ,
  3307.      ' ║ ' || el1               || ' ║ '  || ,
  3308.      Menu.__emptyLine                     || ,
  3309.      ' ╚'  || el                 || '╝'
  3310.  
  3311.   drop el el1
  3312.                     /* create the var with the messages               */
  3313.  
  3314.                     /* message 1 to 98 are error messages             */
  3315.                     /* message 99 and above are normal messages       */
  3316.   msgStr.1   = ,
  3317. /*  1 */     '_' ,
  3318. /*  2 */     'Inputfile_"%1"_not_found' ,
  3319. /*  3 */     'InputFile_"%1"_is_empty' ,
  3320. /*  4 */     'Error_opening_the_inputFile_"%1"' ,
  3321. /*  5 */     'InputQueue_"%1"_does_not_exist' ,
  3322. /*  6 */     'InputQueue_"%1"_is_empty' ,
  3323. /*  7 */     'The_line_%1_of_the_input_channel_is_invalid_(The_line_reads:_%2)' ,
  3324. /*  8 */     'Menu_"%1"_not_found' ,
  3325. /*  9 */     'Menu_"%1"_is_empty' ,
  3326. /* 10 */     'Line_%1:_Menu_%2_already_defined' ,
  3327. /* 11 */     '_' ,
  3328. /* 12 */     'Line_%1:_Macroname_to_long' ,
  3329. /* 13 */     'Invalid_menu_command_found:_"%1"' ,
  3330. /* 14 */     'Line_%1:_Macro_"%2"_already_defined' ,
  3331. /* 15 */     'Line_%1:_Keyword_missing' ,
  3332. /* 16 */     'Line_%1:_Invalid_MENUITEM/ACTION_keyword_found' ,
  3333. /* 17 */     'Line_%1:_Invalid_REXX_statement,_the_line_reads_"%2"' ,
  3334. /* 18 */     'Line_%1:_Onlinehelp_%2_already_defined' ,
  3335. /* 19 */     'Line_%1:_Onlinehelp_to_large_(maximun_is_14_lines)' ,
  3336. /* 20 */     'Line_%1:_Invalid_menu_name' ,
  3337. /* 21 */     'Parameter_"%1"_is_invalid' ,
  3338. /* 99 */     '%1_error_in_line_%2,_rc_=_%3_%4' ,
  3339. /*100 */     'Checking_the_parameter_...' ,
  3340. /*101 */     'Reading_the_menu_description_...' ,
  3341. /*102 */     'Creating_the_menu_structure_...' ,
  3342. /*103 */     'Preparing_the_menu_...' ,
  3343. /*104 */     '%1' ,
  3344. /*105 */     '_' ,
  3345. /*106 */     '_' ,
  3346. /*107 */     '_' ,
  3347. /*108 */     '_' ,
  3348. /*109 */     '_' ,
  3349. /*110 */     'List_of_all_menu_descriptions_in' ,
  3350. /*111 */     'Choose_a_menu_from_the_list' ,
  3351. /*112 */     'Your_choice:' ,
  3352. /*113 */     'Press_any_key_to_continue' ,
  3353. /*114 */     'List_of_all_macros_defined_in' ,
  3354. /*115 */     '***_Keyword_"%1"_not_defined_for_this_menu!_***_' ,
  3355. /*116 */     'List_of_all_menus_called_so_far' ,
  3356. /*117 */     'Choose_a_macro_from_the_list' ,
  3357. /*118 */     'Error_evaluating_"%1"'
  3358.  
  3359. RETURN
  3360.  
  3361. /* ------------------------------------------------------------------ */
  3362. /* function: get a string                                             */
  3363. /*                                                                    */
  3364. /* call:     I!.__GetMessage msg_no {{,arg1} {...} {,arg9}}           */
  3365. /*                                                                    */
  3366. /* where:    msg_no - the message number                              */
  3367. /*           arg1 .. arg9 - values for the placeholder in the         */
  3368. /*                          messages                                  */
  3369. /*                                                                    */
  3370. /* returns:  the message text                                         */
  3371. /*                                                                    */
  3372. /*                                                                    */
  3373. I!.__GetMessage: PROCEDURE expose (exposeList)
  3374.   parse arg msgNo , mP1, mP2, mP3, mP4, mP5, mP6, mP7, mP8, mP9
  3375.  
  3376.                     /* install a local error handler                  */
  3377.   SIGNAL ON SYNTAX Name I!.__GetMessage1
  3378.  
  3379.                     /* first check for an external GETMSG routine     */
  3380.                     /* try to call the user defined GetMsg routine    */
  3381.   if Global.__GetMsgRoutine <> '' then
  3382.   do
  3383.     interpret 'call "' || Global.__GetMsgRoutine || ,
  3384.                    '" Global.__BaseMsgNo+msgNo,,'   ,
  3385.                    ' mP1, mP2, mP3, mP4, mP5, mP6, mP7, mP8, mP9 '
  3386.  
  3387.                     /* the next statement is only executed, if the   */
  3388.                     /* interpret statement above didn't cause an     */
  3389.                     /* error                                         */
  3390.  
  3391.  
  3392.     return result   /* external routine found and executed, return    */
  3393.                     /* the result                                     */
  3394.   end /* if Global.__GetMsgRoutine <> '' then */
  3395.  
  3396. I!.__GetMessage1:
  3397.                     /* This code is only executed if either there's   */
  3398.                     /* no GetMsgRoutine defined or the call of the    */
  3399.                     /* GetMsgRoutine caused an error                  */
  3400.  
  3401.                     /* reinstall the error handler                    */
  3402.   SIGNAL ON SYNTAX
  3403.  
  3404.                     /* no external routine found or executed, use the */
  3405.                     /* builtin messages                               */
  3406.  
  3407.   j = MsgNo
  3408.   if MsgNo >= 99 then
  3409.     j = MsgNo - 77
  3410.  
  3411.   msgText = translate( word( msgStr.1, j ), ' ', '_' )
  3412.  
  3413.                     /* replace the placeholder with the values        */
  3414.   if pos( '%', msgText ) <> 0 then
  3415.     do j = 1 to 9
  3416.       pString = '%' || j
  3417.  
  3418.       do forever
  3419.         if pos( pString, msgText ) = 0 then
  3420.           leave
  3421.         parse var msgText part1 ( pString ) part2
  3422.         msgText = part1 || arg( j+1 ) || part2
  3423.       end /* do forever */
  3424.  
  3425.     end /* do j = 1 to 9 */
  3426.  
  3427.   if msgNo < 100 then
  3428.     return 'ERROR:' msgNo ':' msgText
  3429.  
  3430.                     /* the next statement is only executed if the     */
  3431.                     /* previous IF statement is false                 */
  3432. RETURN MsgText
  3433.  
  3434. /* ------------------------------------------------------------------ */
  3435. /* ----------- the following code is for developing only ------------ */
  3436.  
  3437. /**DEBUG** Delete this line before using the debugging routines!!!
  3438.  
  3439. /* ------------------------------------------------------------------ */
  3440. /* function: show all variables defined for the routine calling       */
  3441. /*           this routine.                                            */
  3442. /*                                                                    */
  3443. /* call:     ShowDefinedVariables {N} {,varMask} {,outpufFile}        */
  3444. /*                                                                    */
  3445. /* where:    N - no pause if the screen is full                       */
  3446. /*           varMask - mask for the variables                         */
  3447. /*           outputFile - write the variable list to this file        */
  3448. /*                                                                    */
  3449. /* returns:  nothing                                                  */
  3450. /*                                                                    */
  3451. /* note:     This routine needs the Dave Boll's DLL RXU.DLL!          */
  3452. /*           Be aware that the special REXX variables SIGL, RC and    */
  3453. /*           RESULT are changed if you call this routine!             */
  3454. /*                                                                    */
  3455. /*                                                                    */
  3456. ShowDefinedVariables:
  3457.   sdv.__dummy = trace('OFF')
  3458.  
  3459.   parse upper arg SDV.__pauseMode, SDV.__varMask, SDV.__outPut
  3460.  
  3461.   if SDV.__outPut <> '' then
  3462.     if SDV.__pauseMode = '' then
  3463.       SDV.__pauseMdoe = 'N'
  3464.  
  3465.                                 /* install a local error handler      */
  3466.   signal on syntax name SDV.__RXUNotFound
  3467.  
  3468.                                 /* load the necessary DLL function    */
  3469.   call rxFuncDrop 'RxVLIst'
  3470.   call rxFuncAdd 'RxVlist', 'RXU', 'RxVList'
  3471.  
  3472.   call rxFuncDrop 'RxPullQueue'
  3473.   call rxFuncAdd 'RxPullQueue', 'RXU', 'RxPullQueue'
  3474.  
  3475.                                 /* create a queue for the variables   */
  3476.   SDV.__newQueue = rxqueue( 'create' )
  3477.  
  3478.                                 /* the 'D' parameter of the RxVList   */
  3479.                                 /* functions won't pause if the       */
  3480.                                 /* screen is full                     */
  3481.   SDV.__thisRC = RxVList( SDV.__varMask, 'V' , SDV.__newQueue )
  3482.  
  3483.                                 /* ignore local variables of this     */
  3484.                                 /* routine                            */
  3485.   SDV.__thisRC = SDV.__thisRC
  3486.  
  3487.   call LineOut SDV.__outPut , '  ' || copies( '─',76 )
  3488.  
  3489.   if SDV.__thisRC <> 0 then
  3490.   do
  3491.  
  3492.     call LineOut SDV.__outPut , '  Defined variable(s) and their values:'
  3493.     SDV.__i = 0
  3494.  
  3495.     do SDV.__n = 1 to SDV.__ThisRC
  3496.       if SDV.__i >= 23 & ,
  3497.          SDV.__pauseMode <> 'N' then
  3498.       do
  3499.         ADDRESS 'CMD' 'PAUSE'
  3500.         SDV.__i = 0
  3501.       end /* if */
  3502.       SDV.__varName = RxPullQueue( SDV.__newQueue, 'Nowait', 'SDV.__dummy' )
  3503.       SDV.__varValue = RxPullQueue( SDV.__newQueue, 'Nowait', 'SDV.__dummy' )
  3504.  
  3505.                                 /* ignore local variables of this     */
  3506.                                 /* routine                            */
  3507.       if left( SDV.__varName, 6 ) <> 'SDV.__' then
  3508.       do
  3509.         call LineOut SDV.__outPut , '     ' || SDV.__varName || ' = "' || SDV.__varValue || '"'
  3510.         SDV.__i = SDV.__i+1
  3511.       end /* if right( ... */
  3512.  
  3513.     end /* do */
  3514.  
  3515.                         /* delete the queue for the variables         */
  3516.     call rxqueue 'Delete', SDV.__newQueue
  3517.   end
  3518.   else
  3519.     call LineOut SDV.__outPut , '  No variables defined.'
  3520.  
  3521.   call LineOut SDV.__outPut , '  ' || copies( '─',76 )
  3522.  
  3523.   call LineOut SDV.__outPut                                  
  3524.  
  3525.                         /* delete local variables                     */
  3526.   drop SDV.
  3527. RETURN ' '                                                  
  3528.  
  3529.                         /* error exit for ShowDefinedVariables        */
  3530. SDV.__RXUNotFound:
  3531.   call LineOut SDV.__outPut , 'ShowDefinedVariables: RXU.DLL not found'
  3532. RETURN 255
  3533.  
  3534. /* ------------------------------------------------------------------ */
  3535.  
  3536.    Delete this line before using the debugging routines!!!    **DEBUG**/
  3537. /* ------------------------------------------------------------------ */
  3538.  
  3539.  
  3540.