home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Spezial / SPEZIAL2_97.zip / SPEZIAL2_97.iso / ANWEND / TOOLS / GBJ111 / getobj.cmd < prev    next >
OS/2 REXX Batch file  |  1997-01-25  |  144KB  |  3,113 lines

  1. /* ------------------------------------------------------------------ */
  2. /* GETOBJ.CMD - create a list of all WPS objects                      */
  3. /*                                                                    */
  4. /* (c) Copyright Bernd Schemmer 1994 - 1997                           */
  5. /*                                                                    */
  6. /* Author                                                             */
  7. /*   Bernd Schemmer                                                   */
  8. /*   Baeckerweg 48                                                    */
  9. /*   D-60316 Frankfurt am Main                                        */
  10. /*   Germany                                                          */
  11. /*   Compuserve: 100104,613                                           */
  12. /*                                                                    */
  13. /* Description                                                        */
  14. /*   GETOBJ creates a list containing the data for all objects in a   */
  15. /*   folder (and it's sub folder). For each object the title, the     */
  16. /*   class, the setup string and the location is shown.               */
  17. /*   GETOBJ can also create a REXX program with SysCreateObject calls */
  18. /*   to recreate the objects.                                         */
  19. /*                                                                    */
  20. /* Limitations                                                        */
  21. /*   GETOBJ "knows" only the settings known by the current version of */
  22. /*   the DLL WPTOOLS.DLL. So, before using this program you should    */
  23. /*   carefully read the documentation for the DLL WPTOOLS.DLL in the  */
  24. /*   file WPTOOLS.TXT!                                                */
  25. /*                                                                    */
  26. /*                          IMPORTANT                                 */
  27. /*                                                                    */
  28. /*   If you use GETOBJ to create a REXX program to recreate the       */
  29. /*   objects you MUST manually check the created REXX program before  */
  30. /*   using it!!!                                                      */
  31. /*   The REXX program created by GETOBJ creates the objects in the    */
  32. /*   following order:                                                 */
  33. /*     1. the folders & sub folders                                   */
  34. /*     2. the objects                                                 */
  35. /*   and                                                              */
  36. /*     3. the shadows.                                                */
  37. /*                                                                    */
  38. /*   GETOBJ won't check further dependencies! GETOBJ also won't       */
  39. /*   insert code to register the WPS classes possibly necessary       */
  40. /*   for the objects into the created REXX program!                   */
  41. /*                                                                    */
  42. /*   GETOBJ IS NOT INTENDED TO SAVE OR RESTORE YOUR DESKTOP!!!        */
  43. /*                                                                    */
  44. /* History                                                            */
  45. /*   28.04.1995 /bs v1.00                                             */
  46. /*     - initial release                                              */
  47. /*   10.07.1995 /bs v1.10                                             */
  48. /*     - now you can also use single quotes around the starting       */
  49. /*       folder                                                       */
  50. /*     - added code to check the object definitions for the created   */
  51. /*       REXX program                                                 */
  52. /*   25.01.1997 /bs v1.11                                             */
  53. /*     - corrected some bugs                                          */
  54. /*     - added a work around for a bug in the lineout function in     */
  55. /*       Object REXX                                                  */
  56. /*     - replaced WPTOOLS.DLL with the new DLL necessary for WARP 4   */
  57. /*       (from WPTOOLS v1.9)                                          */
  58. /*                                                                    */
  59. /* Notes                                                              */
  60. /*   This program needs the OS/2 DLL REXXUTIL.                        */
  61. /*   This program also needs Henk Kelders famous DLL WPTOOLS.DLL      */
  62. /*   (included in this package).                                      */
  63. /*   THESE DLLs MUST BE IN A DIRECTORY IN THE LIBPATH OR IN THE       */
  64. /*   CURRENT DIRECTORY!!!                                             */
  65. /*                                                                    */
  66. /* Credits                                                            */
  67. /*   The procedure to detect the desktop directory                    */
  68. /*    "GetDesktopDirectory"                                           */
  69. /*   was written by                                                   */
  70. /*     Georg Haschek (haschek at vnet.ibm.com).                       */
  71. /*   The SHELL sort routine                                           */
  72. /*      "ShellSort"                                                   */
  73. /*   was written by                                                   */
  74. /*     Steve Pitts (CompuServe: 100331,1134).                         */
  75. /*   Thanks to both.                                                  */
  76. /*                                                                    */
  77. /*   The DLL WPTOOLS.DLL needed by this program is from               */
  78. /*     Henk Kelder (CompuServe: 100321,3650                           */
  79. /*                  Fido: 2:280/801.339@fidonet.org)                  */
  80. /*   Thanks to him for the permission to distribute WPTOOLS.DLL with  */
  81. /*   this program.                                                    */
  82. /*                                                                    */
  83. /*   Also thanks to all, who send me hints & bug reports for GETOBJ.  */
  84. /*                                                                    */
  85. /* Usage                                                              */
  86. /*   GETOBJ {!|{!}startFolder} {/L:logfile}                           */
  87. /*          {/REXX=file} {/NOREXX}                                    */
  88. /*          {/STAT} {/NOSTAT}                                         */
  89. /*          {/LIST} {/NOLIST}                                         */
  90. /*          {/H} {/Silent} {/NoSound} {/NoAnsi}                       */
  91. /*                                                                    */
  92. /* where:                                                             */
  93. /*   startFolder - fully qualified name of the start folder           */
  94. /*                 If the name of the folder is preceeded with a '!'  */
  95. /*                 GETOBJ won't process the sub folders.              */
  96. /*                 The default start folder is the desktop folder.    */
  97. /*                 Note:                                              */
  98. /*                 Enclose the foldername with single or double       */
  99. /*                 quotes if it contains blanks or special chars.     */
  100. /*                                                                    */
  101. /*   !           - process the desktop folder without sub folders     */
  102. /*                                                                    */
  103. /*   /L:logFile - logfile is the name of the logfile :-)              */
  104. /*                This parameter is case-sensitive!                   */
  105. /*                default: do not use a logfile                       */
  106. /*                                                                    */
  107. /* /REXX{=file} - create a REXX program to reCreate the objects.      */
  108. /*                File is the fully qualified name for the REXX       */
  109. /*                program (def.: CROBJ.CMD in the current directory). */
  110. /*                If the file already exists, GETOBJ creates a backup */
  111. /*                before rewriting it.                                */
  112. /*                This Parameter suppresses the creation of an object */
  113. /*                list and the statistics. To create the REXX program */
  114. /*                AND the object list and/or the statistics use the   */
  115. /*                the parameter in the following sequence:            */
  116. /*                /REXX{=file} /LIST /STAT                            */
  117. /*   /NOREXX    - do not create a REXX program (default)              */
  118. /*                                                                    */
  119. /*   /LIST      - create an object list and write it to the screen.   */
  120. /*                (Default)                                           */
  121. /*                Use the parameter /L:logfile to redirect the list   */
  122. /*                to a file.                                          */
  123. /*                                                                    */
  124. /*   /NOLIST    - do not create an object list.                       */
  125. /*                                                                    */
  126. /*   /STAT      - create the statistics and write them to the screen. */
  127. /*                (Default)                                           */
  128. /*                Use the parameter /L:logfile to redirect the        */
  129. /*                statistics to a file.                               */
  130. /*                                                                    */
  131. /*   /NOLIST    - do not create the statistics.                       */
  132. /*                                                                    */
  133. /*   /H         - show usage, you may also use                        */
  134. /*                /h, /?, /HELP, -h, -H, -HELP or -?                  */
  135. /*                                                                    */
  136. /*   /Silent    - suppress all messages (except error messages)       */
  137. /*                You should also use the parameter /L:logfile if you */
  138. /*                use this parameter!                                 */
  139. /*                You may also set the environment variable SILENT to */
  140. /*                "1" to suppress all messages.                       */
  141. /*                                                                    */
  142. /*   /NoSound   - suppress all sounds. You may also set the           */
  143. /*                environment variable SOUND to "0" to suppress the   */
  144. /*                sounds.                                             */
  145. /*                                                                    */
  146. /*   /NoAnsi    - do not use ANSI codes. You may also set the         */
  147. /*                environment variable ANSI to "0" to suppress the    */
  148. /*                use of ANSI codes.                                  */
  149. /*                                                                    */
  150. /* Note:                                                              */
  151. /*   You must use at least one blank to separate the parameter.       */
  152. /*                                                                    */
  153. /* examples:                                                          */
  154. /*                                                                    */
  155. /*   GETOBJ /L:C:\DESKTOP.LST                                         */
  156. /*     - write a list of all objects on your desktop and in the sub   */
  157. /*       folders of the desktop to the file C:\DESKTOP.LST            */
  158. /*                                                                    */
  159. /*   GETOBJ ! /L:C:\DESKTOP.LST                                       */
  160. /*     - write a list of all objects on the desktop to the file       */
  161. /*       C:\DESKTOP.LST. Do not process the sub folders.              */
  162. /*                                                                    */
  163. /*   GETOBJ "C:\DESKTOP\My Folder" /L:C:\MyFolder.LST                 */
  164. /*     - write a list of all objects in the folder C:\DESKTOP\SYSTEM  */
  165. /*       and in the sub folders of ths folders to the file            */
  166. /*       C:\SYSTEM.LST.                                               */
  167. /*                                                                    */
  168. /*   GETOBJ "!C:\DESKTOP\My Folder" /L:C:\MyFolder.LST                */
  169. /*     - write a list of all objects in the folder C:\DESKTOP\SYSTEM  */
  170. /*       to the file C:\SYSTEM.LST. Do not process sub folders.       */
  171. /*                                                                    */
  172. /*                                                                    */
  173. /* Distribution                                                       */
  174. /*   This version of GETOBJ is Freeware. You can use and share it as  */
  175. /*   long as you neither delete nor change any file or program in the */
  176. /*   archiv!                                                          */
  177. /*   Please direct your inquiries, complaints, suggestions, bug lists */
  178. /*   etc. to the address noted above.                                 */
  179. /*                                                                    */
  180. /*   Contact Henk Kelder if you want to distribute the DLL            */
  181. /*   WPTOOLS.DLL with your program.                                   */
  182. /*                                                                    */ 
  183. /*                                                                    */
  184. /*                                                                    */
  185. /* Based on TEMPLATE.CMD v3.05, TEMPLATE is (c) 1996 Bernd Schemmer,  */
  186. /* Baeckerweg 48, D-60316 Frankfurt, Germany, Compuserve: 100104,613  */
  187. /*                                                                    */
  188. /* ------------------------------------------------------------------ */
  189.  
  190. /* ------------------------------------------------------------------ */
  191. /*** change the following values to your need                       ***/
  192.  
  193.                   global. = ''  /* init the stem global. with ''      */
  194.  
  195.          global.__Version = '1.11'      /* Version of YOUR program    */
  196.  
  197.        global.__SignOnMsg = 1   /* set to 0 if you do not want the    */
  198.                                 /* program start and end messages     */
  199.  
  200.          global.__NeedCID = 0   /* set to 1 if you need CID support   */
  201.  
  202.       global.__NeedColors = 1   /* set to 1 if you want colored msgs  */
  203.  
  204.   global.__NeedPatchCheck = 0   /* set to 1 if you want the program   */
  205.                                 /* to search for a patched version of */
  206.                                 /* this program                       */
  207.  
  208. /***                End of variables to change                      ***/
  209. /*      HINT: The further program code is in the function MAIN        */
  210.  
  211. /***        End of Part 1 of the source code of TEMPLATE.CMD        ***/
  212.  
  213.  
  214. /***       Start of Part 2 of the source code of TEMPLATE.CMD       ***/
  215.  
  216. /*************** DO NOT CHANGE THE FOLLOWING LINES ********************/
  217.  
  218.                         /* names of the global variables, which all   */
  219.                         /* procedures must know                       */
  220.   exposeList = 'prog. screen. I!. global. exposeList ' exposeList
  221.  
  222.                         /* check the type of the base message number  */
  223.   if datatype( global.__BaseMsgNo, 'W' ) <> 1 then
  224.     global.__BaseMsgNo = 1000
  225.  
  226.                         /* init internal variables                    */
  227.   I!. = ''
  228.                         /* save default STDOUT and STDERR             */
  229.   if symbol( 'prog.__STDOUT' ) = 'VAR' then
  230.     I!.__2 = prog.__STDOUT
  231.   if symbol( 'prog.__STDERR' ) = 'VAR' then
  232.     I!.__3 = prog.__STDERR
  233.  
  234.                         /* init the stems prog. & screen.             */
  235.   parse value '' with prog. screen.
  236.  
  237.                         /* reset the timer                            */
  238.   call time 'R'
  239.  
  240.                         /* restore default STDOUT and STDERR          */
  241.   prog.__STDOUT = I!.__2;    prog.__STDERR = I!.__3
  242.  
  243.                         /* get the number of the first line with      */
  244.                         /* user code                                  */
  245.   call I!.__GetUserCode
  246.  
  247. /* ------------------------------------------------------------------ */
  248. /* install the error handler                                          */
  249.  
  250.                         /* break errors (CTRL-C)                      */
  251.   CALL ON HALT        NAME I!.__UserAbort
  252.                         /* syntax errors                              */
  253.   SIGNAL ON SYNTAX    NAME I!.__ErrorAbort
  254.                         /* using of not initialisized variables       */
  255.   SIGNAL ON NOVALUE   NAME I!.__ErrorAbort
  256.                         /* failure condition                          */
  257.   SIGNAL ON FAILURE   NAME I!.__ErrorAbort
  258.                         /* error condition                            */
  259.   SIGNAL ON ERROR     NAME I!.__ErrorAbort
  260.                         /* disk not ready condition                   */
  261.   SIGNAL ON NOTREADY  NAME I!.__ErrorAbort
  262.  
  263. /* ------------------------------------------------------------------ */
  264. /* init the variables                                                 */
  265.  
  266.                         /* get & save the parameter                   */
  267.   parse arg I!.__RealParam 1 prog.__Param
  268.  
  269.                         /* init the variables                         */
  270.  
  271.                         /* define exit code values                    */
  272.   global.__ErrorExitCode = 255
  273.      global.__OKExitCode = 0
  274.  
  275.                         /* init the compound variable prog.           */
  276.   call I!.__InitProgStem
  277.  
  278.                         /* define the variables for CID programs      */
  279.   call I!.__InitCIDVars
  280.  
  281.                         /* init the program exit code                 */
  282.   prog.__ExitCode = global.__OKExitCode
  283.  
  284.                         /* check the parameter and env. variables     */
  285.                         /* This must run before I!.__InitColorVars!   */
  286.   call I!.__chkPandE
  287.  
  288.                         /* define the color variables                 */
  289.   call I!.__InitColorVars
  290.  
  291.                         /* check if there is a logfile parameter      */
  292.   call I!.__SetLogVars
  293.  
  294. /* ------------------------------------------------------------------ */
  295. /* show program start message                                         */
  296.  
  297.   call I!.__SignMsg
  298.  
  299. /* ------------------------------------------------------------------ */
  300. /* check if there is a patched version of this program                */
  301.  
  302.   call I!.__CheckPatch
  303.  
  304. /* ------------------------------------------------------------------ */
  305.  
  306.                         /* check for a help parameter                 */
  307.   if pos( translate( word( prog.__Param,1 ) ), ,
  308.           '/?/H/HELP/-?-H-HELP' ) <> 0 then
  309.   do
  310.     prog.__exitCode = 253
  311.  
  312.     call I!.__CallUserProc 1, 'ShowUsage'
  313.  
  314.     SIGNAL I!.__programEnd
  315.  
  316.   end /* pos( translate( ... */
  317.  
  318. /* ------------------------------------------------------------------ */
  319.  
  320.                         /* call the main procedure                    */
  321.   call I!.__CallUserProc 2, 'main' strip( prog.__Param )
  322.  
  323.                         /* use the return code of 'main' as exitcode  */
  324.                         /* if a returncode was returned               */
  325.   if symbol( 'I!.__UserProcRC' ) == 'VAR' then
  326.     prog.__ExitCode = I!.__UserProcRC
  327.  
  328. /* ------------------------------------------------------------------ */
  329. /* house keeping                                                      */
  330.  
  331. I!.__ProgramEnd:
  332.  
  333.                                 /* call the exit routines             */
  334.   do while prog.__exitRoutines <> ''
  335.  
  336.                         /* delete the name of the routine from the    */
  337.                         /* list to avoid endless loops!               */
  338.     parse var prog.__ExitRoutines I!.__cer prog.__ExitRoutines
  339.  
  340.     call I!.__CallUserProc 1, I!.__cer
  341.  
  342.   end /* do while prog.__ExitRoutines <> '' */
  343.  
  344.                                 /* restore the current directory      */
  345.   if symbol( 'prog.__CurDir' ) == 'VAR' then
  346.     call directory prog.__CurDir
  347.  
  348.                                 /* show sign off message              */
  349.   call I!.__SignMsg 'E'
  350.  
  351. EXIT prog.__ExitCode
  352.  
  353. /* ------------------------------------------------------------------ */
  354. /*-function: show the sign on or sign off message                     */
  355. /*                                                                    */
  356. /*-call:     I!.__SignMsg which                                       */
  357. /*                                                                    */
  358. /*-where:    which - 'E' - show the sign off message                  */
  359. /*                         else show the sign on message              */
  360. /*                                                                    */
  361. /*-returns:  nothing                                                  */
  362. /*                                                                    */
  363. I!.__SignMsg: PROCEDURE expose (exposeList)
  364.   if global.__SignOnMsg <> 1 then
  365.     RETURN
  366.  
  367.                         /* default: program start message             */
  368.   i = 12
  369.  
  370.   if arg(1) = 'E' then
  371.   do
  372.     i = 13
  373.                         /* program end message                        */
  374.     i!.__rc1 = prog.__ExitCode
  375.  
  376.                                 /* check if the exit code is decimal  */
  377.                                 /* and convert it to hexadecimal if   */
  378.                                 /* possible                           */
  379.     if dataType( prog.__ExitCode, 'W' ) then
  380.     do
  381.       if prog.__ExitCode < 0 then
  382.         prog.__ExitCode = 65536 + prog.__ExitCode
  383.       i!.__rc2 = D2X( prog.__ExitCode )
  384.     end /* if .. */
  385.  
  386.   end /* if arg(1) = 'E' then */
  387.  
  388.   screen.__CurColor = screen.__SignOnColor
  389.   call Log I!.__GetMsg( i, prog.__Name, global.__Version, date(),,
  390.                         time(), i!.__rc1, i!.__rc2 )
  391.   screen.__CurColor = screen.__NormalColor
  392. RETURN
  393.  
  394. /* ------------------------------------------------------------------ */
  395. /*-function: call a user defined routine                              */
  396. /*           (avoid errors if the routine is not defined)             */
  397. /*                                                                    */
  398. /*-call:     I!.__CallUserProc errorAction, procName {procParameter}  */
  399. /*                                                                    */
  400. /*-where:    errorAction - action, if procName is not defined         */
  401. /*                         0: do nothing (only set the RC)            */
  402. /*                         1: show a warning and set the RC           */
  403. /*                         2: abort the program                       */
  404. /*           procName - name of the procedure                         */
  405. /*           procParameter - parameter for the procedure              */
  406. /*                                                                    */
  407. /*-returns:  1 - ok                                                   */
  408. /*           0 - procname not found                                   */
  409. /*                                                                    */
  410. /*-output:   I!.__UserProcRC - Returncode of the called procedure     */
  411. /*                             (dropped if the proedure don't         */
  412. /*                             return a value)                        */
  413. /*                                                                    */
  414. I!.__CallUserProc: PROCEDURE expose (exposeList) result rc sigl
  415.   parse arg I!.__ErrorAction , I!.__ProcN I!.__ProcP
  416.  
  417.   I!.__thisRC = 0
  418.   drop I!.__UserProcRC
  419.  
  420.   iLine = 'call ' I!.__ProcN
  421.   if prog.__Trace = 1 & I!.__ProcN = 'main' then
  422.     iLine = 'trace ?a;'|| iLine
  423.  
  424. /** DO NOT CHANGE, ADD OR DELETE ONE OF THE FOLLOWING SEVEN LINES!!! **/
  425.   I!.__ICmdLine = GetLineNo()+2+(I!.__ProcP <> '')*2               /*!*/
  426.   if I!.__ProcP = '' then                                          /*!*/
  427.     interpret iLine                                                /*!*/
  428.   else                                                             /*!*/
  429.     interpret iLine "I!.__ProcP"                                   /*!*/
  430. /** DO NOT CHANGE, ADD OR DELETE ONE OF THE PRECEEDING SEVEN LINES!! **/
  431.  
  432. /* Caution: The CALL statement changes the variable RESULT!           */
  433.   I!.__0 = trace( 'off' )
  434.  
  435.   I!.__thisRC = 1
  436.   if symbol( 'RESULT' ) == 'VAR' then
  437.     I!.__UserProcRC = value( 'RESULT' )
  438.     
  439.                     /* this label is used if the interpret command    */
  440.                     /* ends with an error                             */
  441. I!.__CallUserProc2:
  442.  
  443.   if I!.__ThisRC = 0 then
  444.   do
  445.     if I!.__ErrorAction = 2 then
  446.       call ShowError global.__ErrorExitCode , ,
  447.                    I!.__GetMsg( 1, I!.__ProcN )
  448.  
  449.     if I!.__ErrorAction = 1 then
  450.       call ShowWarning I!.__GetMsg( 1 , I!.__ProcN )
  451.   end /* if I!.__thisRC = 0 then */
  452.  
  453. RETURN I!.__thisRC
  454.  
  455. /* ------------------------------------------------------------------ */
  456. /*-function: set the variables for the logfile handling               */
  457. /*                                                                    */
  458. /*-call:     I!.__SetLogVars                                          */
  459. /*                                                                    */
  460. /*-input:    prog.__Param - parameter for the program                 */
  461. /*                                                                    */
  462. /*-output:   prog.__LogFile     - name of the logfile (or NUL)        */
  463. /*           prog.__LogSTDERR   - string to direct STDERR into the    */
  464. /*                                logfile                             */
  465. /*           prog.__LogSTDOUT   - string to direct STDOUT into the    */
  466. /*                                logfile                             */
  467. /*           prog.__LogAll      - string to direct STDOUT and STDERR  */
  468. /*                                into the logfile                    */
  469. /*           prog.__LogFileParm - string to inherit the logfile       */
  470. /*                                parameter to a child CMD            */
  471. /*           prog.__Param       - program parameter without the       */
  472. /*                                logfile parameter                   */
  473. /*                                                                    */
  474. /*-returns:  nothing                                                  */
  475. /*                                                                    */
  476. I!.__SetLogVars: PROCEDURE expose (exposeList)
  477.  
  478.   parse var prog.__Param prog.__param '/L:' logFileName ' ' rest
  479.   prog.__param = prog.__Param rest
  480.  
  481.                         /* avoid an error if the drive is not ready   */
  482.   SIGNAL OFF NOTREADY
  483.  
  484.                         /* default log device is the NUL device       */
  485.   prog.__LogFile = 'NUL'
  486.  
  487.   if logFileName <> '' then
  488.   do
  489.                         /* check if we can write to the logfile       */
  490.     logStatus = stream( logFileName, 'c', 'OPEN WRITE')
  491.     if logStatus <> 'READY:' then
  492.     do
  493.       prog.__LogFileParm = ''
  494.  
  495.       call ShowWarning I!.__GetMsg( 2, logFileName, logStatus )
  496.  
  497.     end /* if logStatus <> 'READY:' then */
  498.     else
  499.     do
  500.                         /* close the logfile                          */
  501.       call stream logFileName, 'c', 'CLOSE'
  502.  
  503.                         /* get the fully qualified name of the        */
  504.                         /* logfile                                    */
  505.                         /*                                      v3.04 */
  506.       parse upper value stream( logFileName, 'c', 'QUERY EXIST' ) WITH prog.__LogFile
  507.  
  508.       prog.__LogFileParm = '/L:' || prog.__LogFile
  509.     end /* else */
  510.   end /* if prog.__LogFile <> '' then */
  511.  
  512.                         /* variable to direct STDOUT of an OS/2       */
  513.                         /* program into the logfile                   */
  514.   prog.__LogSTDOUT = ' 1>>' || prog.__LogFile
  515.  
  516.                         /* variable to direct STDERR of an OS/2       */
  517.                         /* program into the logfile                   */
  518.   prog.__LogSTDERR = ' 2>>' || prog.__LogFile
  519.  
  520.                         /* variable to direct STDOUT and STDERR of    */
  521.                         /* an OS/2 program into the log file          */
  522.   prog.__LogALL = prog.__LogSTDERR || ' 1>>&2'
  523.  
  524. RETURN
  525.  
  526. /* ------------------------------------------------------------------ */
  527. /*-function: check the parameter and the environment variables for    */
  528. /*           the runtime system                                       */
  529. /*                                                                    */
  530. /*-call:     I!.__chkPandE                                            */
  531. /*                                                                    */
  532. /*-input:    prog.__Param - parameter for the program                 */
  533. /*           prog.__env - name of the environment                     */
  534. /*                                                                    */
  535. /*-output:   prog.__QuietMode - 1 if parameter '/Silent' found        */
  536. /*                              or environment variable SILENT set    */
  537. /*           prog.__NoSound   - 1 if parameter '/NoSound' found       */
  538. /*                              or environment variable SOUND set     */
  539. /*           screen.          - "" if parameter '/NoANSI' found       */
  540. /*                              or environment variable ANSI set      */
  541. /*           prog.__Param     - remaining parameter for the procedure */
  542. /*                              MAIN.                                 */
  543. /*           prog.__Trace     - 1 if parameter '/Trace' found         */
  544. /*                              or if the environment variable        */
  545. /*                              RXTTRACE is set to MAIN               */
  546. /*                                                                    */
  547. /*-returns:  nothing                                                  */
  548. /*                                                                    */
  549. I!.__chkPandE: PROCEDURE expose (exposeList)
  550.  
  551.   global.__verbose = value( 'VERBOSE' ,, prog.__env )
  552.  
  553.   o!.0 = 4                              /* no. of known parameters    */
  554.                                         /* and environment variables  */
  555.  
  556.   o!.1.parm = '/SILENT'                 /* parameter name             */
  557.   o!.1.env  = 'SILENT'                  /* name of the env. var       */
  558.   o!.1.vals = 'ON 1'                    /* possible values for the    */
  559.                                         /* environment variable       */
  560.   o!.1.stmt = 'prog.__QuietMode=1'      /* statement to execute       */
  561.                                         /* if this parameter was      */
  562.                                         /* entered or the environment */
  563.                                         /* variable is set            */
  564.  
  565.   o!.2.parm = '/NOSOUND'                /* turn sound off             */
  566.   o!.2.env  = 'SOUND'
  567.   o!.2.vals = 'OFF 0'
  568.   o!.2.stmt = 'prog.__NoSound=1'
  569.  
  570.   o!.3.parm = '/NOANSI'                 /* turn ANSI support off      */
  571.   o!.3.env  = 'ANSI'
  572.   o!.3.vals = 'OFF 0'
  573.   o!.3.stmt = 'global.__NeedColors=0'
  574.  
  575.   o!.4.parm = '/TRACE'          /* exeucte MAIN in single step mode   */
  576.   o!.4.env  = 'RXTTRACE'
  577.   o!.4.vals = 'MAIN'
  578.   o!.4.stmt = 'prog.__Trace=1'
  579.  
  580.   do i = 1 to o!.0
  581.                         /* check the parameter                        */
  582.     j = wordPos( o!.i.parm, translate( prog.__Param ) )
  583.     if j = 0 then       /* no parameter found, check the env. var     */
  584.       j = wordPos( translate( value( o!.i.env ,, prog.__env ) ) ,,
  585.                     o!.i.vals )
  586.     else                /* parameter found, delete the parameter      */
  587.       prog.__Param = strip( delWord( prog.__Param, j,1 ) )
  588.  
  589.                         /* if j is not zero either the parameter was  */
  590.                         /* found or the environment variable is set   */
  591.     if j <> 0 then
  592.       interpret o!.i.stmt
  593.   end /* do i = 1 to o!.0 */
  594.  
  595. RETURN
  596.  
  597. /* ------------------------------------------------------------------ */
  598. /*-function:  convert a file or directory name to OS conventions      */
  599. /*            by adding a leading and trailing double quote           */
  600. /*                                                                    */
  601. /*-call:      convertNameToOS dir_or_file_name                        */
  602. /*                                                                    */
  603. /*-where:     dir_or_file_name = name to convert                      */
  604. /*                                                                    */
  605. /*-returns:   converted file or directory name                        */
  606. /*                                                                    */
  607. ConvertNameToOS: PROCEDURE expose (exposeList)
  608.   parse arg fn
  609. RETURN '"' || fn || '"'                                      /* v3.06 */
  610.  
  611. /* ------------------------------------------------------------------ */
  612. /*-function: flush the default REXX queue                             */
  613. /*                                                                    */
  614. /*-call:     FlushQueue                                               */
  615. /*                                                                    */
  616. /*-returns:  ''                                                       */
  617. /*                                                                    */
  618. FlushQueue: /* PROCEDURE expose (exposeList) */
  619.   do while QUEUED() <> 0
  620.     parse pull
  621.   end /* do while QUEUED() <> 0 */
  622. RETURN ' '                                                   /* v3.03 */
  623.  
  624. /* ------------------------------------------------------------------ */
  625. /*-function: include a file if it exists                              */
  626. /*                                                                    */
  627. /*-call:     TryInclude( IncludeFile )                                */
  628. /*                                                                    */
  629. /*-where:    IncludeFile = name of the file to include                */
  630. /*                                                                    */
  631. /*-output:   prog.__rc = 0 - include file executed                    */
  632. /*           else: file not found                                     */
  633. /*                                                                    */
  634. /*-returns:  ''                                                       */
  635. /*                                                                    */
  636. TryInclude:
  637.   parse upper arg I!.__IncFileName
  638.   prog.__rc = 1
  639.  
  640.   if I!.__IncFileName = '' then
  641.     RETURN ' '                                               /* v3.03 */
  642.  
  643.   if stream( I!.__IncFileName,'c','QUERY EXIST' ) = '' then
  644.     RETURN ' '                                               /* v3.03 */
  645.  
  646.   prog.__rc = 0
  647.  
  648.   /* execute INCLUDE */
  649.  
  650. /* ------------------------------------------------------------------ */
  651. /*-function: include a file                                           */
  652. /*                                                                    */
  653. /*-call:     Include( IncludeFile )                                   */
  654. /*                                                                    */
  655. /*-where:    IncludeFile = name of the file to include                */
  656. /*                                                                    */
  657. /*-returns:  ''                                                       */
  658. /*                                                                    */
  659. Include:
  660.   parse upper arg I!.__IncFileName
  661.  
  662.                         /* check if the include file exists           */
  663.   if stream( I!.__IncFileName, 'c', 'QUERY EXIST' ) == '' then
  664.     call ShowError global.__ErrorExitCode, ,
  665.                    I!.__GetMsg( 3, I!.__IncFileName )
  666.  
  667.                         /* read and interpret the include file        */
  668.   do I!.__IncLineNO = 1 while lines( I!.__IncFileName ) <> 0
  669.     I!.__IncCurLine = ''
  670.                         /* save the absolute position of the start of */
  671.                         /* this line for the error handler            */
  672.     I!.__IncCurLinePos = stream(I!.__IncFileName,'c','SEEK +0')
  673.  
  674.                         /* handle multi line statements               */
  675.     do forever
  676.       I!.__IncCurLine = I!.__IncCurLine ,
  677.                         strip( lineIn( I!.__IncFileName ) )
  678.  
  679.       if right( I!.__IncCurLine,1 ) <> ',' then
  680.         leave
  681.  
  682.                         /* statement continues on the next line       */
  683.       if lines( I!.__IncFileName ) == 0 then
  684.         call ShowError global.__ErrorExitCode ,,
  685.              I!.__GetMsg( 4, I!.__IncFileName )
  686.  
  687.                         /* the next lines is only executed if the IF */
  688.                         /* statement above is FALSE                  */
  689.       I!.__IncCurLine = substr( I!.__IncCurLine,1, ,
  690.                                 length( I!.__IncCurLine )-1 )
  691.  
  692.     end /* do forever */
  693.  
  694.     I!.__IncActive = 1
  695.     interpret I!.__IncCurLine
  696.     I!.__IncActive = 0
  697.  
  698.   end /* do I!.__IncLineNO = 1 while lines( I!.__IncFileName ) <> 0 ) */
  699.  
  700.                         /* close the include file!                    */
  701.   call stream I!.__IncFileName, 'c', 'CLOSE'
  702.  
  703.                     /* do NOT return a NULL string ('')!        v3.03 */
  704.                     /* Due to a bug in the CMD.EXE this will    v3.03 */
  705.                     /* cause the error SYS0008 after the 32nd   v3.03 */
  706.                     /* call of this function!                   v3.03 */
  707. RETURN ' '
  708.  
  709. /* ------------------------------------------------------------------ */
  710. /*-function: init color variables                                     */
  711. /*                                                                    */
  712. /*-call:     I!.__InitColorVars                                       */
  713. /*                                                                    */
  714. /*-returns:  nothing                                                  */
  715. /*                                                                    */
  716. I!.__InitColorVars: /* PROCEDURE expose (exposeList) */
  717.  
  718.   if 1 == global.__NeedColors then
  719.   do
  720.     escC = '1B'x || '['                                      /* v3.04 */
  721.  
  722.     t1 = 'SAVEPOS RESTPOS ATTROFF' ,                         /* v3.05 */
  723.          'HIGHLIGHT NORMAL BLINK INVERS INVISIBLE'           /* v3.05 */
  724.  
  725.     t2 = 's u 0;m 1;m 2;m 5;m 7;m 8;m'                       /* v3.05 */
  726.  
  727.     screen.__DELEOL = escC || 'K'                            /* v3.05 */
  728.  
  729.     do i = 1 to 8                                            /* v3.05 */
  730.  
  731.       call value 'SCREEN.__' || word( t1, i ) ,,             /* v3.05 */
  732.                  escC || word( t2,i )                        /* v3.05 */
  733.  
  734.                                                              /* v3.05 */
  735.       s = word( 'BLACK RED GREEN YELLOW BLUE MAGNENTA CYAN WHITE', i )
  736.       call value 'SCREEN.__FG' || s,,                        /* v3.05 */
  737.                  escC || 29+i || ';m'                        /* v3.05 */
  738.       call value 'SCREEN.__BG' || s,,                        /* v3.05 */
  739.                  escC || 39+i || ';m'                        /* v3.05 */
  740.     end /* do i = 1 to 8 */                                  /* v3.05 */
  741.  
  742.     drop t1 t2 s i                                           /* v3.05 */
  743.  
  744. /* --------------------------- */
  745.                         /* define color variables                     */
  746.     screen.__ErrorColor  = screen.__AttrOff || screen.__Highlight || ,
  747.                            screen.__FGYellow || screen.__bgRed
  748.  
  749.     screen.__NormalColor = screen.__AttrOff ||                       ,
  750.                            screen.__fgWhite || screen.__bgBlack
  751.  
  752.     screen.__DebugColor  = screen.__AttrOff || screen.__Highlight || ,
  753.                            screen.__fgBlue || screen.__bgWhite
  754.  
  755.     screen.__PromptColor = screen.__AttrOff || screen.__Highlight || ,
  756.                            screen.__fgYellow || screen.__bgMagnenta
  757.  
  758. /* +++++++++++++++ DO NOT USE THE FOLLOWING COLORS! +++++++++++++++++ */
  759.     screen.__SignOnColor = screen.__AttrOff || screen.__Highlight || ,
  760.                            screen.__fggreen || screen.__bgBlack
  761.  
  762.     screen.__PatchColor  = screen.__AttrOff || screen.__Highlight || ,
  763.                            screen.__fgcyan || screen.__bgRed
  764. /* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
  765.  
  766.                             /* set the default color                  */
  767.     screen.__CurColor    = screen.__NormalColor
  768.  
  769.                             /* turn ANSI word wrapping on             */
  770.     if prog.__QuietMode <> 1 then
  771.       call CharOut prog.__STDOUT, '1B'x || '[7h'
  772.  
  773.   end /* if 1 == global.__NeedColors then */
  774.  
  775. RETURN
  776.  
  777. /* ------------------------------------------------------------------ */
  778. /*-function: init the stem prog.                                      */
  779. /*                                                                    */
  780. /*-call:     I!.__InitProgStem                                        */
  781. /*                                                                    */
  782. /*-returns:  nothing                                                  */
  783. /*                                                                    */
  784. /*-Note:     DO NOT ADD ANY CODE TO THIS ROUTINE!                     */
  785. /*                                                                    */
  786. I!.__InitProgStem: /* PROCEDURE expose (exposeList) */
  787.   prog.__Defparms = ' {/L:logfile} {/H} {/Silent} {/NoAnsi} {/NoSound} {/Trace}'
  788.  
  789.                         /* get drive, path and name of this program   */
  790.   parse upper source . . prog.__FullName
  791.         prog.__Drive = filespec( 'D', prog.__FullName )
  792.          prog.__Path = filespec( 'P',  prog.__FullName )
  793.          prog.__Name = filespec( 'N',  prog.__FullName )
  794.  
  795.                                                              /* v3.05 */
  796.  parse upper value 'V3.06 1 80 25 OS2ENVIRONMENT' directory() with ,
  797.              prog.__Version ,         /* version of template    v3.05 */
  798.              prog.__UserAbort ,       /* allow useraborts       v3.05 */
  799.              prog.__ScreenCols ,      /* def. screen cols       v3.05 */
  800.              prog.__ScreenRows ,      /* def. screen rows       v3.05 */
  801.              prog.__env ,             /* def. environment       v3.05 */
  802.              prog.__CurDir            /* current directory      v3.05 */
  803.  
  804.                                 /* install a local error handler      */
  805.   SIGNAL ON SYNTAX Name I!.__InitProgStem1
  806.                                 /* try to call SysTextScreenSize()    */
  807.   parse value SysTextScreenSize() with prog.__ScreenRows prog.__ScreenCols
  808.  
  809. I!.__InitProgStem1:
  810.  
  811. RETURN
  812.  
  813. /* ------------------------------------------------------------------ */
  814. /*-function: init the variables for CID programs (only if the value   */
  815. /*           of the variable global.__NeedCID is 1)                   */
  816. /*                                                                    */
  817. /*-call:     I!.__InitCIDVars                                         */
  818. /*                                                                    */
  819. /*-returns:  nothing                                                  */
  820. /*                                                                    */
  821. /*-Note:     DO NOT ADD ANY CODE TO THIS ROUTINE!                     */
  822. /*           Returncodes as defined by LCU 2.0                        */
  823. /*                                                                    */
  824. I!.__InitCIDVars: /* PROCEDURE expose (exposeList) exposeList CIDRC. */
  825.  
  826.   if 1 == global.__NeedCID then
  827.   do
  828.  
  829.     I!.__cidRCValues = ,                                     /* v3.05 */
  830.       '0000'x 'SUCCESSFUL_PROGRAM_TERMINATION',              /* v3.05 */
  831.       '0004'x 'SUCCESSFUL_LOG_WARNING_MESSAGE',              /* v3.05 */
  832.       '0008'x 'SUCCESSFUL_LOG_ERROR_MESSAGE',                /* v3.05 */
  833.       '0012'x 'SUCCESSFUL_LOG_SEVERE_ERROR',                 /* v3.05 */
  834.       '0800'x 'DATA_RESOURCE_NOT_FOUND',                     /* v3.05 */
  835.       '0804'x 'DATA_RESOURCE_ALREADY_IN_USE',                /* v3.05 */
  836.       '0808'x 'DATA_RESOURCE_NOAUTHORIZATION',               /* v3.05 */
  837.       '0812'x 'DATA_PATH_NOT_FOUND',                         /* v3.05 */
  838.       '0816'x 'PRODUCT_NOT_CONFIGURED',                      /* v3.05 */
  839.       '1200'x 'STORAGE_MEDIUM_EXCEPTION',                    /* v3.05 */
  840.       '1204'x 'DEVICE_NOT_READY',                            /* v3.05 */
  841.       '1208'x 'NOT_ENOUGH_DISKSPACE',                        /* v3.05 */
  842.       '1600'x 'INCORRECT_PROGRAM_INVOCATION',                /* v3.05 */
  843.       '1604'x 'UNEXPECTED_CONDITION',                        /* v3.05 */
  844.       'FE00'x 'SUCCESSFULL_REBOOT',                          /* v3.05 */
  845.       'FE04'x 'SUCCESSFULL_REBOOT_WITH_WARNING',             /* v3.05 */
  846.       'FE08'x 'SUCCESSFULL_REBOOT_WITH_ERRMSG',              /* v3.05 */
  847.       'FE12'x 'SUCCESSFULL_REBOOT_WITH_SERVER_ERRMSG',       /* v3.05 */
  848.                                                              /* v3.05 */
  849.     do i = 1 to words( I!.__cidRCValues ) by 2               /* v3.05 */
  850.       call value 'CIDRC.__' || word( I!.__cidRCValues,i+1 ),,
  851.                  c2d( word( I!.__cidRCValues,i ),2 )         /* v3.05 */
  852.                                                              /* v3.05 */
  853.     end /* do i = 1 to words( I!.__cidRCValues ) by 2 */     /* v3.05 */
  854.                                                              /* v3.05 */
  855.     drop I!.__cidRCValues                                    /* v3.05 */
  856.  
  857.  
  858.                         /* xx = next state of the program             */
  859. /*    CIDRC.__successfull_reboot_with_callback = C2D('FFxx'x, 2);     */
  860.  
  861.                         /* define exit code values                    */
  862.     global.__ErrorExitCode = CIDRC.__unexpected_condition
  863.        global.__OKExitCode = CIDRC.__successful_program_termination
  864.  
  865.                         /* add the stem CIDRC. to the exposeList      */
  866.     exposeList = exposeList 'CIDRC. '
  867.   end /* if 1 == global.__NeedCID then */
  868.  
  869. RETURN
  870.  
  871.  
  872. /***        End of Part 2 of the source code of TEMPLATE.CMD        ***/
  873.  
  874. /***       Start of Part 3 of the source code of TEMPLATE.CMD       ***/
  875.  
  876. /* ------------------------------------------------------------------ */
  877. /*-function:  load a dll                                              */
  878. /*                                                                    */
  879. /*-call:                                                              */
  880. /*   thisRC = LoadDll( registerFunction, dllName, entryPoint,         */
  881. /*                     ,{deRegisterFunction},{checkFunction}          */
  882. /*                     ,{IgnoreRxFuncAddRC},{RegisterErrorRC}         */
  883. /*                     ,{errorAction}                                 */
  884. /*                                                                    */
  885. /*-where:                                                             */
  886. /*         registerFunc = name of the dll init function               */
  887. /*                        (e.g. "SysLoadFuncs")                       */
  888. /*              dllName = name of the dll                             */
  889. /*                        (e.g. "REXXUTIL")                           */
  890. /*           entryPoint = entryPoint for the dll init function        */
  891. /*                        (e.g. "SysLoadFuncs")                       */
  892. /*       deRegisterFunc = name of the dll exit function               */
  893. /*                        (e.g. "SysDropFuncs")                       */
  894. /*                        If this parameter is entered, the           */
  895. /*                        deRegisterFunction is automaticly called    */
  896. /*                        at program end if the loading of the dll    */
  897. /*                        was successfull.                            */
  898. /*            checkFunc = function which must be loaded if the dll is */
  899. /*                        loaded (def.: none -> always load the dll)  */
  900. /*                        Note:                                       */
  901. /*                        Do not use the registerFunction for this    */
  902. /*                        parameter! A good candidate for this        */
  903. /*                        parameter is the deRegisterFunction.        */
  904. /*    IgnoreRxFuncAddRC = 1: ignore the rc from rxFuncAdd             */
  905. /*                        0: do not ignore the rc from rxFuncAdd      */
  906. /*                        (def.: 0)                                   */
  907. /*                        Note: Always set this parameter to 1 if     */
  908. /*                              using the program under WARP.         */
  909. /*       RegisterErroRC = returncode of the dll init function         */
  910. /*                        indicating a load error                     */
  911. /*                        (def. none, -> ignore the returncode of the */
  912. /*                         dll init function)                         */
  913. /*           actionCode = 1: abort program if loading failed          */
  914. /*                        0: do not abort program if loading failed   */
  915. /*                        (def.: 1)                                   */
  916. /*                                                                    */
  917. /*-returns:                                                           */
  918. /*   0 - loading failed                                               */
  919. /*   1 - dll loaded                                                   */
  920. /*   2 - dll already loaded                                           */
  921. /*                                                                    */
  922. /*-Note:                                                              */
  923. /*   See the routine MAIN for some examples for using LoadDLL.        */
  924. /*   LoadDLL can only handle dlls with an init function to register   */
  925. /*   the further routines in the dll (like the function SysLoadFuncs  */
  926. /*   in the dll REXXUTIL).                                            */
  927. /*                                                                    */
  928. LoadDll:  PROCEDURE expose (exposeList)
  929.   parse arg regFunc , ,
  930.             dllName , ,
  931.             entryPoint , ,
  932.             deregFunc , ,
  933.             checkFunc , ,
  934.             ignoreRXFuncAddRC, ,
  935.             registerErrorRC, ,
  936.             errorAction
  937.  
  938.                         /* check the necessary parameters             */
  939.   if '' == entryPoint | '' == dllName | '' == regFunc then
  940.     call ShowError global.__ErrorExitCode, I!.__GetMsg( 6 )
  941.  
  942.   if '' == ignoreRXFuncAddRC then
  943.     ignoreRXFuncAddRc = 0
  944.  
  945.   if '' == errorAction then
  946.     errorAction = 1
  947.  
  948.   I!.__LoadDLLRc = 0
  949.                         /* if the 'checkFunc' is missing, we          */
  950.                         /* assume that the dll is not loaded          */
  951.   dllNotLoaded = 1
  952.   if ( checkFunc <> '' ) then
  953.     dllNotLoaded = rxFuncQuery( checkFunc )
  954.  
  955.   if dllNotLoaded then
  956.   do
  957.                         /* first deRegister the function        v3.01 */
  958.     call rxFuncDrop regFunc                                  /* v3.01 */
  959.  
  960.                         /* load the dll and register the init         */
  961.                         /* function of the dll                        */
  962.     rxFuncAddRC = rxFuncAdd( regFunc, dllName, entryPoint )
  963.  
  964.     if \ rxFuncAddRC | ignoreRxFuncAddRC then
  965.     do
  966.  
  967.       I!.__DllInitRC = 0
  968.       if I!.__CallUserProc( 0, regFunc ) == 0 then
  969.         I!.__DllInitRC = 'ERROR'
  970.  
  971.       if ( registerErrorRC <> '' & I!.__DLLInitRC == registerErrorRC ) | ,
  972.          ( I!.__DllInitRC == 'ERROR' ) then
  973.         nop
  974.       else
  975.       do
  976.                         /* add the dll deregister function to the     */
  977.                         /* program exit routine list                  */
  978.         if DeregFunc <> '' then
  979.           if \ rxFuncQuery( DeregFunc ) then
  980.             prog.__ExitRoutines = prog.__ExitRoutines || ' ' || ,
  981.                                   DeregFunc
  982.  
  983.         I!.__LoadDLLRc = 1
  984.       end /* else */
  985.     end /* if \ rxFuncAddRC | ignoreRxFuncAddRC then */
  986.   end /* if dllNotLoaded then */
  987.   else
  988.     I!.__LoadDLLRc = 2  /* dll is already loaded                      */
  989.  
  990.   if 1 == errorAction & 0 == I!.__LoadDLLRC then
  991.     call ShowError global.__ErrorExitCode,,
  992.                    I!.__GetMsg( 5, dllName )
  993.  
  994. RETURN I!.__LoadDLLRc
  995.  
  996. /* ------------------------------------------------------------------ */
  997. /*-function: show a string with word wrapping                         */
  998. /*                                                                    */
  999. /*-call:     showString Prefix, thisString                            */
  1000. /*                                                                    */
  1001. /*-where:                                                             */
  1002. /*           Prefix = prefix for the first line (e.g. "*-*" or "#" to */
  1003. /*                    use # leading blanks, # = 1 ... n )             */
  1004. /*           thisString - string to print                             */
  1005. /*                                                                    */
  1006. /*-returns:  ''                                                       */
  1007. /*                                                                    */
  1008. ShowString: PROCEDURE EXPOSE (exposeList)
  1009.   parse arg Prefix, thisStr
  1010.  
  1011.   maxLineL = prog.__ScreenCols-4
  1012.  
  1013.   if datatype( prefix, 'W' ) == 1 then
  1014.     prefix = copies( ' ' , prefix )
  1015.  
  1016.   maxWordL = maxLineL - length( prefix )
  1017.  
  1018.   thisRC = 0
  1019.   curStr = ''
  1020.  
  1021.   do i = 1 to words( thisStr)
  1022.     pStr = 0
  1023.  
  1024.     curStr = curStr || word( thisStr, i ) || ' '
  1025.  
  1026.     if length( curStr || prefix ||  word( thisStr, i+1 ) ) > maxLineL then
  1027.       pStr = 1
  1028.  
  1029.     if 1 == pStr | i == words( thisStr ) then
  1030.     do
  1031.       if length( prefix || curStr ) > prog.__ScreenCols then
  1032.       do until curStr = ''
  1033.         parse var curStr curStr1 =(maxWordL) ,
  1034.                                   curStr
  1035.         call log left( prefix || curStr1, prog.__ScreenCols )
  1036.         prefix = copies( ' ', length( prefix ) )
  1037.       end /* if length( ... then do until */
  1038.       else
  1039.         call Log left( prefix || curStr, prog.__ScreenCols )
  1040.  
  1041.       curStr = ''
  1042.       prefix = copies( ' ', length( prefix ) )
  1043.     end /* if 1 == pStr | ... */
  1044.  
  1045.   end /* do i = 1 to words( thisStr */
  1046.  
  1047. RETURN ' '                                                   /* v3.03 */
  1048.  
  1049. /* ------------------------------------------------------------------ */
  1050. /*-function: show a warning message                                   */
  1051. /*                                                                    */
  1052. /*-call:     showWarning message                                      */
  1053. /*                                                                    */
  1054. /*-where:    warningMessage - warning Message                         */
  1055. /*                                                                    */
  1056. /*-returns:  ''                                                       */
  1057. /*                                                                    */
  1058. ShowWarning: PROCEDURE expose (exposeList)
  1059.   parse arg wMsg
  1060.  
  1061.   screen.__CurColor = screen.__ErrorColor
  1062.  
  1063.   call I!.__LogStart
  1064.  
  1065.   call ShowString I!.__GetMsg( 7 ) || ' ', wMsg || '!'
  1066.   call I!.__LogSeparator
  1067.  
  1068.   screen.__CurColor = screen.__NormalColor
  1069.   call Log
  1070.  
  1071. RETURN ' '                                                   /* v3.03 */
  1072.  
  1073. /* ------------------------------------------------------------------ */
  1074. /*-function: show an error message and end the program                */
  1075. /*                                                                    */
  1076. /*-call:     ShowError exitCode, errorMessage                         */
  1077. /*                                                                    */
  1078. /*-where:    ExitCode - no of the error (= program exit code)         */
  1079. /*           errorMessage - error Message                             */
  1080. /*                                                                    */
  1081. /*-returns:  nothing                                                  */
  1082. /*                                                                    */
  1083. /*-Note:     THIS ROUTINE WILL NOT COME BACK!!!                       */
  1084. /*                                                                    */
  1085. ShowError: PROCEDURE expose (exposeList)
  1086.   parse arg prog.__ExitCode, I!.__errMsg
  1087.  
  1088.   I!.__QM = prog.__QuietMode
  1089.                         /* turn quiet mode off                        */
  1090.   prog.__QuietMode = ''
  1091.  
  1092.   screen.__CurColor = screen.__ErrorColor
  1093.  
  1094.   call I!.__LogStart
  1095.  
  1096.   call Log left( I!.__GetMsg( 8, prog.__Name , prog.__ExitCode ) ,,
  1097.                  prog.__ScreenCols )
  1098.   call ShowString 1, I!.__errMsg || '!'
  1099.  
  1100.   call I!.__LogSeparator
  1101.   call Log
  1102.                         /* restore quiet mode status                  */
  1103.   prog.__QuietMode = I!.__QM
  1104.  
  1105.   if prog.__NoSound <> 1 then
  1106.   do
  1107.     call beep 537,300
  1108.     call beep 237,300
  1109.     call beep 537,300
  1110.   end /* if prog.__NoSound <> 1 then */
  1111.  
  1112. SIGNAL I!.__ProgramEnd
  1113.  
  1114. RETURN
  1115.  
  1116. /* ------------------------------------------------------------------ */
  1117. /*-function: log a debug message and clear the rest of the line       */
  1118. /*                                                                    */
  1119. /*-call:     logDebugMsg message                                      */
  1120. /*                                                                    */
  1121. /*-where:    message - message to show                                */
  1122. /*                                                                    */
  1123. /*-returns:  ''                                                       */
  1124. /*                                                                    */
  1125. /*-Note:     You do not need the 'call' keyword to use this routine.  */
  1126. /*                                                                    */
  1127. LogDebugMsg: PROCEDURE expose (exposeList)
  1128.   if global.__verbose <> '' then
  1129.   do
  1130.     parse arg dMsg
  1131.     screen.__CurColor = screen.__DebugColor
  1132.     call Log '+++' dMsg
  1133.     screen.__CurColor = screen.__NormalColor
  1134.   end /* if global.__verbose <> '' then */
  1135. RETURN ' '                                                   /* v3.03 */
  1136.  
  1137. /* ------------------------------------------------------------------ */
  1138. /*-function: write a CR/LF and a separator line to the screen and to  */
  1139. /*           the logfile                                              */
  1140. /*                                                                    */
  1141. /*-call:     I!.__LogStart                                            */
  1142. /*                                                                    */
  1143. /*-returns:  nothing                                                  */
  1144. /*                                                                    */
  1145.  
  1146. /* ------------------------------------------------------------------ */
  1147. /*-function: write a separator line to the screen and to the logfile  */
  1148. /*                                                                    */
  1149. /*-call:     I!.__LogSeparator                                        */
  1150. /*                                                                    */
  1151. /*-returns:  nothing                                                  */
  1152. /*                                                                    */
  1153. I!.__LogStart:
  1154.   call log
  1155. I!.__LogSeparator:
  1156.   call Log ' ' || left('-', prog.__ScreenCols-2, '-' ) || ' '
  1157. RETURN
  1158.  
  1159. /* ------------------------------------------------------------------ */
  1160. /*-function: log a message and clear the rest of the line             */
  1161. /*                                                                    */
  1162. /*-call:     log message                                              */
  1163. /*                                                                    */
  1164. /*-where:    message - message to show                                */
  1165. /*                                                                    */
  1166. /*-returns:  ''                                                       */
  1167. /*                                                                    */
  1168. /*-Note:     You do not need the 'call' keyword to use this routine.  */
  1169. /*                                                                    */
  1170. Log: PROCEDURE expose (exposeList)
  1171.   parse arg msg
  1172.  
  1173.   logmsg = msg
  1174.   do i = 1 to words( prog.__LogExcludeWords )
  1175.     curWord = word( prog.__LogExcludeWords, i )
  1176.    
  1177.     do until j = 0
  1178.       j = Pos( curWord, logmsg )
  1179.       if j <> 0 then
  1180.         logmsg = delstr( logmsg, j, length( curWord ) )
  1181.     end /* do until j = 0 */
  1182.   end /* do i = 1 to words( prog.__LogExcludeWords ) */
  1183.  
  1184.   if prog.__QuietMode <> 1 then
  1185.   do
  1186.  
  1187.     if length( logmsg ) == prog.__ScreenCols  then
  1188.       call charout prog.__STDOUT, screen.__CurColor || ,
  1189.                                   msg || screen.__AttrOff
  1190.     else
  1191.       call lineOut prog.__STDOUT, screen.__CurColor || ,
  1192.                                   msg || screen.__AttrOff ||,
  1193.                                   screen.__DelEOL
  1194.  
  1195.   end /* if prog.__Quietmode <> 1 then */
  1196.  
  1197.   if symbol( 'prog.__LogFile' ) == 'VAR' then
  1198.     if prog.__LogFile <> '' then
  1199.     do
  1200.       call lineout prog.__LogFile, logmsg
  1201.  
  1202.                                 /* close the logfile                  */
  1203.       call stream prog.__LogFile, 'c', 'CLOSE'
  1204.     end /* if prog.__LogFile <> '' then */
  1205.  
  1206. RETURN ' '                                                   /* v3.03 */
  1207.  
  1208. /* ------------------------------------------------------------------ */
  1209. /*-function: check if there is a patched version of this program      */
  1210. /*                                                                    */
  1211. /*-call:     I!.__CheckPatch                                          */
  1212. /*                                                                    */
  1213. /*-returns:  nothing                                                  */
  1214. /*                                                                    */
  1215. /*-Note:     I!.__RealParam must contain the parameters for           */
  1216. /*           this program.                                            */
  1217. /*           The variables prog.__Path and prog.__Name must be set!   */
  1218. /*           This procedure ends the program with an EXIT command!    */
  1219. /*                                                                    */
  1220. I!.__CheckPatch: PROCEDURE expose (exposeList)
  1221.  
  1222.                         /* get the drive with patch cmd files         */
  1223.                         /*                                      v3.04 */
  1224.   parse upper value value( 'PATCHDRIVE',, prog.__env ) with pLW
  1225.  
  1226.   if global.__NeedPatchCheck <> 0 & ( pLW <> '' & pLW <> prog.__Drive ) then
  1227.   do
  1228.  
  1229.     pVer = pLW || prog.__Path || prog.__Name
  1230.  
  1231.                         /* check if a patched program version exists  */
  1232.     if stream( pVer, 'c', 'QUERY EXIST' ) <> '' then
  1233.     do
  1234.       pCmd = pVer || ' ' || I!.__RealParam
  1235.  
  1236.       screen.__CurColor = screen.__PatchColor
  1237.       call Log left( I!.__GetMsg( 9, pver ), prog.__ScreenCols )
  1238.       screen.__CurColor = screen.__AttrOff
  1239.       call I!.__LogSeparator
  1240.  
  1241.       '@cmd /c ' pCmd
  1242.  
  1243.       screen.__CurColor = screen.__AttrOff
  1244.       call I!.__LogSeparator
  1245.       screen.__CurColor = screen.__PatchColor
  1246.       call Log left( I!.__GetMsg( 10, rc ), prog.__ScreenCols )
  1247.  
  1248.       exit rc
  1249.     end /* if stream( ... */
  1250.   end /* if pLW <> '' */
  1251. RETURN
  1252.  
  1253. /* ------------------------------------------------------------------ */
  1254. /*-function: error handler for unexpected errors                      */
  1255. /*                                                                    */
  1256. /*-call:     DO NOT CALL THIS ROUTINE BY HAND!!!                      */
  1257. /*                                                                    */
  1258. /*-returns:  nothing                                                  */
  1259. /*                                                                    */
  1260. /*-input:    I!.__IncActive:                                          */
  1261. /*             if 1 the error occured while executing an include file */
  1262. /*             statement. In this case the following variables are    */
  1263. /*             also used (Note that this variables are automaticly    */
  1264. /*             set by the routine INCLUDE()):                         */
  1265. /*               I!.__IncLineNo                                       */
  1266. /*                 Line no. of the include file                       */
  1267. /*               I!.__IncFileName:                                    */
  1268. /*                 Name of the include file                           */
  1269. /*               I!.__IncCurLinePos:                                  */
  1270. /*                 Fileposition of the first char of the line causing */
  1271. /*                 the error                                          */
  1272. /*                                                                    */
  1273. /*-Note:     THIS FUNCTION ABORTS THE PROGRAM WITH A JUMP TO THE      */
  1274. /*           LABEL I!.__PROGRAMEND!!!                                 */
  1275. /*                                                                    */
  1276. I!.__ErrorAbort:
  1277.  
  1278.                             /* turn ANSI word wrap on                 */   
  1279.   if screen.__CurColor <> '' then
  1280.     call CharOut prog.__STDOUT, '1B'x || '[7h'
  1281.  
  1282.                         /* check if the error occured in the error    */
  1283.                         /* handler                                    */
  1284.   if I!.__errorLineNo == sigl then
  1285.   do
  1286.     call charout 'STDERR:',,
  1287.                                                             '0D0A'x  ,
  1288.        'Fatal Error: Error in the error handler detected!'  '0D0A'x  ,
  1289.                                                             '0D0A'x  ,
  1290.        'Linenumber:       ' || sigl                         '0D0A'x  ,
  1291.        'Errorname:        ' || condition('C')               '0D0A'x  ,
  1292.        'Errordescription: ' || condition('D')               '0D0A'x  ,
  1293.                                                             '0D0A'x  ,
  1294.        'The program exit routines were not called!'         '0D0A'x  ,
  1295.        'Check if "(EXPOSELIST)" is included in the ' || ,
  1296.        'expose lists of all procedures!'                    '0D0A'x
  1297.  
  1298.     call beep 637,300 ; call beep 437,300 ; call beep 637,300
  1299.     exit 255
  1300.  
  1301.   end /* if I!.__errorLineNo == sigl then */
  1302.  
  1303.                         /* get the number of the line causing the     */
  1304.                         /* error                                      */
  1305.   I!.__errorLineNo = sigl
  1306.  
  1307.                         /* get the name of this error                 */
  1308.   I!.__ErrorName = condition('C')
  1309.  
  1310.                         /* get further information for this error     */
  1311.                         /* if available                               */
  1312.   I!.__ErrorCondition = condition('D')
  1313.   if I!.__ErrorCondition <> '' then
  1314.     I!.__ErrorCondition = ' (Desc.: "' || I!.__ErrorCondition || '")'
  1315.  
  1316.   if datatype( prog.__ScreenCols, 'W' ) <> 1 then
  1317.     prog.__ScreenCols = 80
  1318.  
  1319.   if SYMBOL( 'prog.__Name' ) <> 'VAR' | value( 'prog.__Name' ) == '' then
  1320.     if I!.__errorLineNO < I!.__FirstUserCodeLine then
  1321.       I!.__pName = '**Runtime**'
  1322.     else
  1323.       I!.__pName = '***???***'
  1324.   else
  1325.     i!.__pName = prog.__Name
  1326.  
  1327.                         /* reInstall the error handler                */
  1328.   INTERPRET  'SIGNAL ON ' value(condition('C')) ' NAME I!.__ErrorAbort'
  1329.  
  1330.                         /* check, if we should ignore the error       */
  1331.   if value( 'sigl' ) == value( 'I!.__ICmdLine' ) then
  1332.   do
  1333.     I!.__errorLineNo = 0
  1334.     SIGNAL I!.__CallUserProc2
  1335.   end /* if value( ... */
  1336.  
  1337.   screen.__CurColor = screen.__ErrorColor
  1338.  
  1339.   I!.__QM = prog.__QuietMode
  1340.                         /* turn quiet mode off                        */
  1341.   prog.__QuietMode = ''
  1342.  
  1343.                         /* init variables for printing the line       */
  1344.                         /* causing the error to the screen            */
  1345.   I!.__ThisSRCLine = ''
  1346.   I!.__ThisPrefix = ' *-* '
  1347.  
  1348.   call I!.__LogStart
  1349.  
  1350.   call ShowString ' ' || I!.__pName || ' - ', I!.__ErrorName || ,
  1351.                   I!.__ErrorCondition || ' error detected!'
  1352.  
  1353.                         /* check, if the RC is meaningfull for this   */
  1354.                         /* error                                      */
  1355.   if pos( I!.__ErrorName, 'ERROR FAILURE SYNTAX' ) <> 0 then
  1356.   do
  1357.     if datatype(rc, 'W' ) == 1 then
  1358.       if 'SYNTAX' == I!.__ErrorName then
  1359.          if rc > 0 & rc < 100 then
  1360.             call Log left( ' The error code is ' || rc || ,
  1361.                            ', the REXX error message is: ' || ,
  1362.                            errorText( rc ), ,
  1363.                            prog.__ScreenCols )
  1364.          else
  1365.            call log left( ' The error code is ' || rc || ,
  1366.                           ', this error code is unknown.',,
  1367.                           prog.__ScreenCols )
  1368.       else
  1369.         call Log left( ' The RC is ' || rc || '.', prog.__ScreenCols )
  1370.   end /* if pos( ... */
  1371.  
  1372.   if value( 'I!.__IncActive' ) == 1 then
  1373.   do
  1374.                 /* error occured while interpreting an include file   */
  1375.     call ShowString 1, 'The error occured while executing the line ' || ,
  1376.                        I!.__IncLineNo || ' of the include file "' || ,
  1377.                        I!.__IncFileName || '".'
  1378.  
  1379.                         /* reset the file pointer of the include file */
  1380.                         /* to the start of the line causing the error */
  1381.     call stream I!.__IncFileName, 'c', 'SEEK =' || ,
  1382.                                                    I!.__IncCurLinePos
  1383.  
  1384.     I!.__SrcAvailable = stream( I!.__IncFileName, ,
  1385.                                    'c', 'QUERY EXIST' ) <> ''
  1386.   end
  1387.   else
  1388.   do
  1389.     call ShowString 1, 'The error occured in line ' ||,
  1390.                        I!.__errorLineNo || '.'
  1391.  
  1392.     I!.__thisLineNo = I!.__errorLineNo
  1393.  
  1394.                 /* error occured in this file                         */
  1395.                 /* check if the sourcecode is available               */
  1396.     SIGNAL ON SYNTAX   NAME I!.__NoSourceCode
  1397.     I!.__inMacroSpace = 1
  1398.     I!.__SrcAvailable = 0
  1399.     if sourceLine( I!.__errorLineNo ) <> '' then
  1400.       I!.__SrcAvailable = 1
  1401.  
  1402.     SIGNAL ON SYNTAX NAME I!.__ErrorAbort
  1403.     I!.__inMacroSpace = 0
  1404.  
  1405.   end /* else */
  1406.  
  1407.                         /* print the statement causing the error to   */
  1408.                         /* the screen                                 */
  1409.   if 1 == I!.__SrcAvailable then
  1410.   do
  1411.     call Log left( ' The line reads: ', prog.__ScreenCols )
  1412.     I!.__InterpretVar = 0
  1413.  
  1414.                 /* read the line causing the error                    */
  1415.     call I!.__GetSourceLine
  1416.  
  1417.     I!.__FirstToken = strip(word( I!.__ThisSRCLine,1))
  1418.     if translate( I!.__FirstToken ) == 'INTERPRET' then
  1419.     do
  1420.       parse var I!.__ThisSRCLine (I!.__FirstToken) ,
  1421.                 I!.__interpretValue
  1422.       I!.__InterpretVar = 1
  1423.     end /* if I!.__thisLineNo = I!.__errorLineNo */
  1424.  
  1425.                         /* handle multi line statements               */
  1426.     do forever
  1427.       call ShowString I!.__ThisPrefix, I!.__ThisSRCLine
  1428.  
  1429.       if right( strip( I!.__ThisSRCLine),1 ) <> ',' then
  1430.         leave
  1431.  
  1432.       I!.__ThisPrefix = 5
  1433.  
  1434.       call I!.__GetSourceLine
  1435.     end /* do forever */
  1436.  
  1437.     if 1 == I!.__InterpretVar then
  1438.     do
  1439.       I!.__interpretValue = strip( word(I!.__interpretValue,1) )
  1440.  
  1441.       if symbol( I!.__interpretValue ) == 'VAR' then
  1442.       do
  1443.         call Log left( '', prog.__ScreenCols )
  1444.         call Log left( ' The value of "' || I!.__interpretValue || ,
  1445.                        '" is:', prog.__ScreenCols )
  1446.         call ShowString ' >V> ', value( I!.__interpretValue )
  1447.       end /* if symbol( I!.__interpretValue ) = 'VAR' then */
  1448.  
  1449.     end /* if 1 == I!.__InterpretVar */
  1450.  
  1451.   end /* if 1 == I!.__SrcAvailable  then do */
  1452.   else
  1453.     call Log left( ' The sourcecode for this line is not available',,
  1454.                    prog.__ScreenCols )
  1455.  
  1456. I!.__NoSourceCode:
  1457.   SIGNAL ON SYNTAX NAME I!.__ErrorAbort
  1458.  
  1459.   if 1 == I!.__inMacroSpace then
  1460.   do
  1461.     parse source . . I!.__thisProgName
  1462.  
  1463.     if fileSpec( 'D', I!.__thisProgName ) == '' then
  1464.       call ShowString 1, ' The sourcecode for this line is not' || ,
  1465.                          ' available because the program is in' || ,
  1466.                          ' the macro space.'
  1467.     else
  1468.       call ShowString 1, ' The sourcecode for this line is not' || ,
  1469.                          ' available because the program is unreadable.'
  1470.   end /* if 1 == I!.__inMacroSpace then */
  1471.  
  1472.   call I!.__LogSeparator
  1473.   call Log
  1474.  
  1475.   prog.__ExitCode = global.__ErrorExitCode
  1476.  
  1477.   if prog.__NoSound <> 1 then
  1478.   do
  1479.     call beep 137,300;  call beep 337,300;  call beep 137,300
  1480.   end /* if prog.__NoSound <> 1 then */
  1481.  
  1482.   if 'DEBUG' == global.__verbose | prog.__Trace = 1 then
  1483.   do
  1484.                         /* enter interactive debug mode               */
  1485.     trace ?a
  1486.     nop
  1487.   end /* if 'DEBUG' == global.__verbose | ... */
  1488.  
  1489.                         /* restore quiet mode status                  */
  1490.   prog.__QuietMode = I!.__QM
  1491.  
  1492. SIGNAL I!.__programEnd
  1493.  
  1494. /* ------------------------------------------------------------------ */
  1495. /*-function: get the sourceline causing an error (subroutine of       */
  1496. /*           I!.__ErrorAbort)                                         */
  1497. /*                                                                    */
  1498. /*-call:     DO NOT CALL THIS IN YOUR CODE!!!                         */
  1499. /*                                                                    */
  1500. /*-returns:  nothing                                                  */
  1501. /*                                                                    */
  1502. /*-Note:     -                                                        */
  1503. /*                                                                    */
  1504. I!.__GetSourceLine:
  1505.   if 1 == I!.__IncActive then
  1506.     I!.__ThisSRCLine = lineIn( I!.__IncFileName )
  1507.   else
  1508.   do
  1509.     I!.__ThisSRCLine = sourceLine( I!.__ThisLineNo )
  1510.     I!.__ThisLineNo = I!.__ThisLineNo + 1
  1511.   end /* else */
  1512. RETURN
  1513.  
  1514. /* ------------------------------------------------------------------ */
  1515. /*-function: error handler for user breaks                            */
  1516. /*                                                                    */
  1517. /*-call:     DO NOT CALL THIS ROUTINE BY HAND!!!                      */
  1518. /*                                                                    */
  1519. /*-returns:  nothing                                                  */
  1520. /*                                                                    */
  1521. /*-Note:     THIS FUNCTION ABORTS THE PROGRAM WITH A JUMP TO THE      */
  1522. /*           LABEL I!.__PROGRAMEND IF prog.__UserAbort IS NOT 0!!!    */
  1523. /*                                                                    */
  1524. /*           In exit routines you may test if the variable            */
  1525. /*           prog.__ExitCode is 254 to check if the program           */
  1526. /*           was aborted by the user.                                 */
  1527. /*                                                                    */
  1528. I!.__UserAbort:
  1529.   I!.__sSigl = sigl
  1530.  
  1531.                         /* reinstall the error handler                */
  1532.   CALL ON HALT NAME I!.__UserAbort
  1533.  
  1534.                         /* check if user aborts are allowed           */
  1535.   if 0 == prog.__UserAbort then
  1536.     RETURN              /* CTRL-BREAK not allowed                     */
  1537.  
  1538.   I!.__QM = prog.__QuietMode
  1539.  
  1540.                         /* turn quiet mode off                        */
  1541.   prog.__QuietMode = ''
  1542.  
  1543.   call Log
  1544.  
  1545.   screen.__CurColor = screen.__ErrorColor
  1546.   call I!.__LogSeparator
  1547.   call Log left( I!.__GetMsg( 11, I!.__sSigl ), prog.__ScreenCols )
  1548.   call I!.__LogSeparator
  1549.   screen.__CurColor = screen.__NormalColor
  1550.  
  1551.   prog.__ExitCode = 254
  1552.  
  1553.                         /* restore quiet mode status                  */
  1554.   prog.__QuietMode = I!.__QM
  1555.  
  1556. SIGNAL I!.__ProgramEnd
  1557.  
  1558. /* ------------------------------------------------------------------ */
  1559. /*-function: get a message                                            */
  1560. /*                                                                    */
  1561. /*-call:     I!.__GetMsg msgNo {,msgP1} {...,msgP9}                   */
  1562. /*                                                                    */
  1563. /*-returns:  the message or an empty string                           */
  1564. /*                                                                    */
  1565. /*-note:     This routines calls the external routine which name is   */
  1566. /*           saved in the variable 'global.__GetMsg' if this variable */
  1567. /*           is not equal ''.                                         */
  1568. /*                                                                    */
  1569. /*           I!.__GetMsg adds global.__BaseMsgNo to the msgNo.        */
  1570. /*                                                                    */
  1571. I!.__GetMsg: PROCEDURE expose (exposeList)
  1572.   parse arg msgNo, mP1 , mP2 , mP3, mP4, mP5, mP6, mP7, mP8, mP9
  1573.  
  1574.   f = 0
  1575.   t = ''
  1576.  
  1577.   if symbol( 'global.__GetMsg' ) = 'VAR' then
  1578.     if global.__GetMsg <> '' then
  1579.     do
  1580.             /* first check if there's a user defined GetMsg routine   */
  1581.  
  1582.                         /* install a local error handler              */
  1583.       SIGNAL ON SYNTAX Name I!.__GetMsg1
  1584.  
  1585.                     /* try to call the user defined GetMsg routine    */
  1586.       interpret 'call ' global.__GetMsg ' msgNo+global.__BaseMsgNo,,' ,
  1587.                 ' mP1, mP2, mP3, mP4, mP5, mP6, mP7, mP8, mP9 '
  1588.       f = 1
  1589.     end /* if global.__GetMsg <> '' then */
  1590.  
  1591. I!.__GetMsg1:
  1592.  
  1593.   if f = 1 then
  1594.   do
  1595.                         /* user defined GetMsg routine found -- use   */
  1596.                         /* the result                                 */
  1597.     if symbol( 'RESULT' ) == 'VAR' then
  1598.       t = result
  1599.   end /* if result = 0 then */
  1600.   else
  1601.   do
  1602.                         /* user defined GetMsg routine not found --   */
  1603.                         /* use the hardcoded message strings          */
  1604.       msgString =  ,
  1605. /* 1001 */      'Routine_"@1"_not_found',
  1606. /* 1002 */      'Can_not_write_to_the_logfile_"@1",_the_status_of_the_logfile_is_"@2"._Now_using_the_NUL_device_for_logging',
  1607. /* 1003 */      'Include_file_"@1"_not_found' ,
  1608. /* 1004 */      'Unexpected_EOF_detected_while_reading_the_include_file_"@1"' ,
  1609. /* 1005 */      'Error_loading_the_DLL_"@1"' ,
  1610. /* 1006 */      'Invalid_call_to_LOADDLL' ,
  1611. /* 1007 */      '_Warning:' ,
  1612. /* 1008 */      '_@1_-_Error_@2_detected!_The_error_message_is_',
  1613. /* 1009 */      '_Calling_the_patched_version_@1_...' ,
  1614. /* 1010 */      '_..._the_patched_version_endet_with_RC_=_@1' ,
  1615. /* 1011 */      '_Program_aborted_by_the_user_(sigl=@1)' ,
  1616. /* 1012 */      '@1_@2_started_on_@3_at_@4_...' ,
  1617. /* 1013 */      '@1_@2_ended_on_@3_at_@4_with_RC_=_@5_(=''@6''x)' ,
  1618. /* 1014 */      '_Usage:'
  1619.  
  1620.                     /* get the message and translate all underscores  */
  1621.                     /* to blanks                                      */
  1622.     t = translate( word( msgString, msgNo ), ' ', '_'  )
  1623.  
  1624.                     /* replace place holder                           */
  1625.     i = 1
  1626.     do until i > 9
  1627.      j = pos( '@' || i, t )
  1628.      if j <> 0 then
  1629.        t = insert( arg( i+1 ), delStr(t, j, 2) , j-1 )
  1630.      else
  1631.        i = i +1
  1632.     end /* do until i > 9 */
  1633.   end /* else */
  1634. return t
  1635.  
  1636. /* ------------------------------------------------------------------ */
  1637. /*-function: get the line no of the call statement of this routine    */
  1638. /*                                                                    */
  1639. /*-call:     GetLineNo                                                */
  1640. /*                                                                    */
  1641. /*-returns:  the line number                                          */
  1642. /*                                                                    */
  1643. /*                                                                    */
  1644. GetLineNo:
  1645.   RETURN sigl
  1646.  
  1647. /* ------------------------------------------------------------------ */
  1648. /*-function: get the no. of the first line with the user code         */
  1649. /*                                                                    */
  1650. /*-call:     DO NOT CALL THIS ROUTINE BY HAND!!!                      */
  1651. /*                                                                    */
  1652. /*-returns:  nothing                                                  */
  1653. /*                                                                    */
  1654. /*                                                                    */
  1655. I!.__GetUserCode:
  1656.   I!.__FirstUserCodeLine = GetLineNo()+2
  1657. RETURN
  1658.  
  1659. /********************** End of Runtime Routines ***********************/
  1660. /**********************************************************************/
  1661.  
  1662. /***        End of Part 3 of the source code of TEMPLATE.CMD        ***/
  1663.  
  1664. /***       Start of Part 4 of the source code of TEMPLATE.CMD       ***/
  1665.  
  1666. /* ------------------------------------------------------------------ */
  1667. /*-function: main procedure of the program                            */
  1668. /*                                                                    */
  1669. /*-call:     called by the runtime system with:                       */
  1670. /*           => call main parameter_of_the_program <=                 */
  1671. /*                                                                    */
  1672. /*-returns:  program return code                                      */
  1673. /*           If no return code is returned, the value of the variable */
  1674. /*           prog.__ExitCode is returned to the calling program.      */
  1675. /*                                                                    */
  1676. Main: PROCEDURE expose (exposeList)
  1677.                         /* get the parameter of the program           */
  1678.   parse arg thisArgs
  1679.  
  1680. /* ------------------------------ */
  1681.                         /* strings which should not be written in the */
  1682.                         /* log file                                   */
  1683.   prog.__LogExcludeWords = screen.__fgYellow screen.__highlight ,
  1684.                            screen.__AttrOff
  1685.  
  1686. /* ------------------------------ */
  1687.                         /* load the dll REXXUTIL                      */
  1688.   global.__rexxUtilLoaded = LoadDll(,
  1689.      'SysLoadFuncs', ,  /* dll init function                          */
  1690.      'REXXUTIL',     ,  /* dll name                                   */
  1691.      'SysLoadFuncs', ,  /* dll init entry point                       */
  1692.      'SysDropFuncs', ,  /* dll exit function                          */
  1693.      'SysDropFuncs', ,  /* check function                             */
  1694.      1,              ,  /* 1: ignore rc of rxfuncadd                  */
  1695.      '',             ,  /* errorcode of the init function             */
  1696.      1 )                /* 1: abort if loading failed                 */
  1697.                         /* 0: do not abort if loading failed          */
  1698.  
  1699.                         /* load the dll WPTOOLS                       */
  1700.   global.__wptoolsLoaded = LoadDll(,
  1701.      'WPToolsLoadFuncs', ,  /* dll init function                      */
  1702.      'WPTOOLS',          ,  /* dll name                               */
  1703.      'WPToolsLoadFuncs', ,  /* dll init entry point                   */
  1704.      '',                 ,  /* dll exit function                      */
  1705.      'WPToolsQueryObject',, /* check function                         */
  1706.      1,                  ,  /* 1: ignore rc of rxfuncadd              */
  1707.      '',                 ,  /* errorcode of the init function         */
  1708.      1 )                    /* 1: abort if loading failed             */
  1709.                             /* 0: do not abort if loading failed      */
  1710.  
  1711.                             /* deRegister the DLL at program end      */
  1712.   prog.__ExitRoutines = prog.__ExitRoutines ' DeRegisterWPTools '
  1713.  
  1714. /* ------------------------------ */
  1715.  
  1716.                             /* get the real screen size               */
  1717.   parse value SysTextScreenSize() with prog.__screenRows prog.__ScreenCols
  1718.  
  1719. /* ------------------------------ */
  1720.                             /* add the necessary stems to the         */
  1721.                             /* expose list                            */
  1722.   exposeList = exposeList ' objectStem. objectCountStem. ' ,
  1723.                           ' statistics. progTypes. SetupStrStem. ' ,
  1724.                           ' classList. '
  1725.  
  1726.   objectStem. = ''          /* stem with the object data              */
  1727.   objectStem.0 = 0          /* no. of objects found                   */
  1728.  
  1729.  
  1730.   objectCountStem. = 0      /* stem with the object counters          */
  1731.  
  1732.                             /* variable with the class names          */
  1733.   objectCountStem.__ClassNames = ''
  1734.  
  1735.   progTypes. = 0            /* stem with the progtype counters        */
  1736.  
  1737.                             /* variable with the progtype names       */
  1738.   progTypes.__UsedTypes = ''
  1739.  
  1740.  
  1741.   statistics. = 0           /* stem for the statistic data            */
  1742.  
  1743.                             /* default name for the REXX program to   */
  1744.                             /* reCreate the objects                   */
  1745.   defREXXProgram = directory() || '\crobj.cmd'
  1746.  
  1747.                             /* current name for the REXX program to   */
  1748.                             /* reCreate the objects                   */
  1749.   curREXXProgram = defREXXProgram
  1750.  
  1751.   processSubFolders = 1     /* 1 : process sub folders                */
  1752.                             /* else: do not process sub folders       */
  1753.  
  1754.   global.__ShowList = 1         /* 1 : show the object list           */
  1755.   global.__ShowStatistics = 1   /* 1 : show the statistics            */
  1756.   global.__CreateREXXProg = 0   /* 1 : create the REXX program        */
  1757.  
  1758. /* ------------------------------ */
  1759.                             /* check the parameter                    */
  1760.  
  1761.   parameterError = 0        /* 1: error in the parameter              */
  1762.  
  1763.   startFolder = ''
  1764.  
  1765.                             /* check for quotes or double quotes      */
  1766.                             /* around the parameter                   */
  1767.   quoteChar = '"'
  1768.   i = pos( quoteChar , thisArgs )
  1769.   if i = 0 then
  1770.   do
  1771.     quoteChar = "'"
  1772.     i = pos( quoteChar, thisArgs ) 
  1773.   end /* if i = 0 then */
  1774.              
  1775.   if i <> 0 then
  1776.   do
  1777.                         /* There _are_ quotes or double quotes around */
  1778.                         /* the parameter                              */
  1779.     i1 = pos( quoteChar, thisArgs, i+1)
  1780.     parse var thisArgs part1 (quoteChar) startFolder (quoteChar) part2
  1781.  
  1782.     if startFolder = '' | i1 = 0 then
  1783.       call ShowError global.__ErrorExitCode ,,
  1784.            'Invalid parameter found. Use /H for help'
  1785.     else
  1786.       startFolder = quoteChar || startFolder || quoteChar
  1787.  
  1788.     thisArgs = part1 part2
  1789.     drop part1 part2
  1790.   end /* if i <> 0 then */
  1791.  
  1792.                             /* process the parameter                  */
  1793.   do i = 1 to words( thisArgs ) while parameterError = 0
  1794.     curParm = translate( word( thisArgs, i ) )
  1795.     if left( curParm, 1 ) = '/' then
  1796.     do
  1797.       curSwitch = substr( curParm,2 )
  1798.  
  1799.       select
  1800.         when curSwitch = 'STAT' then
  1801.           global.__ShowStatistics = 1
  1802.  
  1803.         when curSwitch = 'NOSTAT' then
  1804.           global.__ShowStatistics = 0
  1805.  
  1806.         when curSwitch = 'LIST' then
  1807.           global.__ShowList = 1
  1808.  
  1809.         when curSwitch = 'NOLIST' then
  1810.           global.__ShowList = 0
  1811.  
  1812.         when curSwitch = 'NOREXX' then
  1813.           global.__CreateREXXProg = 0
  1814.  
  1815.         when left( curSwitch,4 ) = 'REXX' then
  1816.         do
  1817.           global.__CreateREXXProg = 1
  1818.           global.__ShowList = 0
  1819.           global.__ShowStatistics = 0
  1820.           
  1821.           testStr = substr( curSwitch, 5 )
  1822.  
  1823.           if testStr <> '' then          
  1824.             if left( testStr, 1,1 ) = '=' then
  1825.               curREXXProgram = substr( testStr,2 ) 
  1826.             else
  1827.               parameterError = 1
  1828.             
  1829.           if curREXXProgram = '' then
  1830.             parameterError = 1
  1831.           else
  1832.             if fileSpec('P', curREXXProgram ) = '' then
  1833.               curREXXProgram = directory() || '\' || curREXXProgram
  1834.         end /* when left( ... */
  1835.  
  1836.         otherwise
  1837.           parameterError = 1
  1838.  
  1839.       end /* select */
  1840.     end /* if left( curParm, 1 ) = '/' then */
  1841.     else
  1842.     do
  1843.       if startFolder <> '' then
  1844.         call ShowError global.__ErrorExitCode,,
  1845.              'Duplicate foldernames are not possible (' ||,
  1846.              curParm || ')'
  1847.       else
  1848.         startFolder = curParm
  1849.     end /* else */
  1850.   end /* do i = 1 to words( thisArgs ) while ... */
  1851.  
  1852.   if parameterError = 1 then
  1853.     call ShowError global.__ErrorExitCode ,,
  1854.          'Invalid parameter found (' || curParm || ')'
  1855.  
  1856.   startFolder = strip( strip( startFolder ,'B' , quoteChar ) )
  1857.  
  1858.   if left( startFolder, 1 ) = '!' then
  1859.   do
  1860.                         /* startup folder is preceded with a '!' --   */
  1861.                         /* do not process sub folders                 */
  1862.     processSubFolders = 0
  1863.     startFolder = substr( startFolder,2 )
  1864.   end /* if left( startFolder,1 ) = '!' then */
  1865.  
  1866.   if startFolder = '' then
  1867.   do
  1868.                             /* no startup folder entered --           */
  1869.                             /* use the desktop folder as startup      */
  1870.                             /* folder                                 */
  1871.     startFolder = GetDesktopDirectory()
  1872.     if startFolder = '' then
  1873.       call ShowError 2,,
  1874.            'Can not find the desktop directory!'
  1875.   end /* if startFolder = '' then */
  1876.  
  1877.   if right( startFolder, 1 ) = '\' then
  1878.     startFolder = dbrright( startFolder,1 )
  1879.  
  1880.                             /* check if the startup folder exist      */
  1881.   if directory( startFolder ) = '' then
  1882.     call ShowError 1,,
  1883.           'Can not find the folder "' || startFolder || '"'
  1884.  
  1885.                             /* restore the working directory          */
  1886.   call directory prog.__curDir
  1887.  
  1888. /* ------------------------------ */
  1889.  
  1890.                         /* force the saving of the base folder object */
  1891.   global.__OS2Ver = SysOS2Ver()
  1892.   parse var global.__OS2Ver main '.' min
  1893.   if main || min >= 230 then
  1894.   do
  1895.                         /* this function is only possible for         */
  1896.                         /* OS/2 v3.0 and above                        */
  1897.     call SysSaveObject startFolder,0
  1898.   end /* if main || min >= 230 then */
  1899.  
  1900. /* ------------------------------ */
  1901.                         /* init the folder structure                  */
  1902.  
  1903.                         /* Note:                                      */
  1904.                         /* We don't use a recurisve algorithm,        */
  1905.                         /* becauste the maximum depth of nested       */
  1906.                         /* control structs in REXX is limited to 100. */
  1907.   folderStruc.0 = 1
  1908.   folderStruc.1 = startFolder
  1909.  
  1910.   if processSubFolders = 1 then
  1911.   do
  1912.     if prog.__QuietMode <> 1 then
  1913.       call CharOut prog.__STDOUT, ' Detecting the folder structure ... '
  1914.  
  1915.                         /* get the folder structure                   */
  1916.     rc = SysFileTree( startFolder || '\*.*', 'key.', 'DSO' )
  1917.     if rc <> 0 then
  1918.       call ShowWarning ,
  1919.         'Error ' || rc || ' detecting the subfolder(s) in the folder "' || ,
  1920.         startFolder || '"'
  1921.     else
  1922.     do
  1923.     if prog.__QuietMode <> 1 then
  1924.       call LineOut prog.__STDOUT, 'done. ' || ,
  1925.                    AddColor1( , key.0 ) || ,
  1926.                    ' folder(s) found.'
  1927.  
  1928.                         /* prepare the arrays for the shell sort      */
  1929.       do i = 1 to key.0
  1930.         ind.i = i
  1931.       end /* do i = 1 to key.0 */
  1932.  
  1933.                         /* sort the sub folders                       */
  1934.       call ShellSort 2, key.0
  1935.  
  1936.                         /* add the sub folders to the folder stem     */
  1937.       j = folderStruc.0
  1938.       do i = 1 to key.0
  1939.         j = j + 1
  1940.         FolderStruc.j = value( 'key.' || ind.i )
  1941.       end /* do i = 1 to key.0 */
  1942.       folderStruc.0 = j
  1943.  
  1944.     end /* else */
  1945.   end /* if processSubFolders = 1 then */
  1946.  
  1947.  
  1948.                         /* get the object data                        */
  1949.   if prog.__QuietMode <> 1 then
  1950.     call CharOut prog.__STDOUT, ' Detecting the object data ...'
  1951.  
  1952.   do i = 1 to folderStruc.0
  1953.     call ProcessFolder '"' || folderStruc.i || '"' , \processSubFolders
  1954.   end /* do i = 1 to folderStruc.0 */
  1955.  
  1956.   if prog.__QuietMode <> 1 then
  1957.     call LineOut prog.__STDOUT, 'done. ' || ,
  1958.          AddColor1( , objectStem.0 ) || ,
  1959.          ' object(s) found.'
  1960.  
  1961.   if objectStem.0 <> 0 then
  1962.   do
  1963.                         /* show the object data                       */
  1964.     if global.__ShowList = 1 then
  1965.       call ShowObjectData
  1966.  
  1967.                         /* show the statistic data                    */
  1968.     if global.__ShowStatistics = 1 then
  1969.       call ShowStatisticData
  1970.  
  1971.                         /* create the REXX program to reCreate the    */
  1972.                         /* objects                                    */
  1973.     if global.__CreateREXXProg = 1 then
  1974.       call CreateREXXProgram curREXXProgram
  1975.  
  1976.     call log ''
  1977.   end /* if objectStem.0 <> 0 then */
  1978.  
  1979. /* ------------------------------ */
  1980.  
  1981.                         /* exit the program                           */
  1982.   prog.__ExitCode = 0
  1983.  
  1984. RETURN prog.__ExitCode
  1985.  
  1986. /* ------------------------------------------------------------------ */
  1987.  
  1988. /* ------------------------------------------------------------------ */
  1989. /* function: CreateREXXProgram                                        */
  1990. /*                                                                    */
  1991. /* call:     CreateREXXProgram fileName                               */
  1992. /*                                                                    */
  1993. /* where:    fileName - fully qualified name for the REXX program     */
  1994. /*                                                                    */
  1995. /* returns:  1 - okay                                                 */
  1996. /*           else error                                               */
  1997. /*                                                                    */
  1998. /*                                                                    */
  1999. CreateREXXProgram: PROCEDURE expose (exposeList) startFolder
  2000.   parse arg outputFile
  2001.  
  2002.                         /* init the return code                       */
  2003.   thisRC = 1
  2004.  
  2005.   crLF = '0D0A'x
  2006.   
  2007.   if prog.__QuietMode <> 1 then
  2008.     call CharOut prog.__STDOUT ,,
  2009.              ' Creating the REXX program ' || crLF || ,
  2010.              '     ' || AddColor1( '"', outputFile ) || crLF  || ,
  2011.              ' to recreate the objects ...'
  2012.  
  2013.                         /* check if the REXX program already exist    */
  2014.   if stream( outputFile, 'c', 'QUERY EXIST' ) <> '' then
  2015.   do
  2016.                         /* create a backup of the existing program    */
  2017.     call CreateBackupFile outputFile
  2018.  
  2019.                         /* delete the existing program                */
  2020.     '@del ' outputFile '2>NUL 1>NUL'
  2021.     if rc <> 0 then
  2022.       call ShowError 3,,
  2023.            'OS Error ' || rc || ' deleting the file "' || outputFile || '"'
  2024.   end /* if stream( ... */
  2025.  
  2026.                         /* write the header for the REXX program      */
  2027.   call LineOut outputFile ,,
  2028.    '/* ------------------------------------------------------------------ */' crLF ||,
  2029.    '/* REXX program to recreate the objects from the folder               */' crLF ||,
  2030.    '/* ' || left( startFolder, 66 ) ||                                  ' */' crLF ||,
  2031.    '/* ' || left( 'Created on ' || date() || ,
  2032.                   ' at ' || time() || ,
  2033.                   ' with ' || prog.__Name || ,
  2034.                   ' v'  || global.__Version , 66 ) ||                   ' */' crLF ||,
  2035.    '/* ' || left( 'This files contains the data for ' || ,
  2036.                   objectStem.0 || ' objects.', 66 ) ||                  ' */' crLF ||,
  2037.    '/*                                                                    */' crLF ||,
  2038.    '/* ' || left( 'Usage: ' || fileSpec( 'N', outputFile ) , 66 ) ||    ' */' crLF ||,
  2039.    '/*                                                                    */' crLF ||,
  2040.    '/* ------------------------------------------------------------------ */' crLF ||,
  2041.    '                                                                        ' crLF ||,
  2042.    '                                                                        ' crLF ||,
  2043.    '                        /* load the dll REXXUTIL                      */' crLF ||,
  2044.    '  call rxFuncAdd "SysLoadFuncs", "REXXUTIL", "SysLoadFuncs"             ' crLF ||,
  2045.    '  call SysLoadFuncs                                                     ' crLF ||,
  2046.    '                                                                        ' crLF ||,
  2047.    '                        /* ask the user if we should continue         */' crLF ||,
  2048.    '  say "REXX program to recreate the ' || ,
  2049.           objectStem.0 || ,
  2050.           ' saved objects from the folder"                                  ' crLF ||,
  2051.    '  say "  ' || startFolder ||                                          '"' crLF ||,
  2052.    '  say "Saved on ' || date() || ' at ' || time() || ,
  2053.         ' with ' || prog.__Name || ' v' || global.__Version ||            '"' crLF ||,
  2054.    '  say ""                                                                ' crLF ||,
  2055.    '  say "Caution: Check this file carefully before using it!!!"           ' crLF ||,        
  2056.    '  say ""                                                                ' crLF ||,
  2057.    '  call CharOut , "Press Y to recreate the saved objects ... "           ' crLF ||,
  2058.    '  if translate( SysGetKey( "NOECHO" ) ) <> "Y" then exit                ' crLF ||,
  2059.    '  say ""                                                                ' crLF ||,
  2060.    '                                                                        ' crLF ||,
  2061.    '  i = 0                                                                 ' crLF ||,
  2062.    '  objects.0 = i                                                         ' crLF ||,
  2063.    '                        /* stem elements for the folder               */'
  2064.  
  2065.                         /* this variable holds the indices of the     */
  2066.                         /* normal objects (no folders and no shadows) */
  2067.   objectIndizes = ''
  2068.  
  2069.                         /* this variable holds the indices of the     */
  2070.                         /* shadow objects                             */
  2071.   shadowIndizes = ''
  2072.  
  2073.                         /* write the object definitions for the       */
  2074.                         /* folder objects and save the indices for    */
  2075.                         /* the other objects in the variables         */
  2076.                         /* objectIndizes and shadowInidzes            */
  2077.   do i = 1 to objectStem.0
  2078.     if objectStem.i.__FolderName <> '' then
  2079.     do
  2080.                         /* this is a folder object                    */
  2081.       call WriteObjectData i, outputFile
  2082.     end
  2083.     else
  2084.     do
  2085.       if objectStem.i.__class = 'WPShadow' then
  2086.         shadowIndizes = shadowIndizes i             /* normal object  */
  2087.       else
  2088.         objectIndizes = objectIndizes i             /* shadow object  */
  2089.     end /* else */
  2090.   end /* do k = 1 to objectStem.0 */
  2091.  
  2092.   call lineOut outputFile, ''
  2093.   call LineOut outputFile , '                        /* stem elements for the objects              */'
  2094.  
  2095.                         /* write the object definitions for the       */
  2096.                         /* normal objects                             */
  2097.   do i = 1 to words( objectIndizes )
  2098.     call WriteObjectData word( objectIndizes, i ), outputFile
  2099.   end /* do i = 1 to words( objectIndizes ) */
  2100.  
  2101.   call lineOut outputFile, ''
  2102.   call LineOut outputFile , '                        /* stem elements for the shadows              */'
  2103.  
  2104.                         /* write the object definitions for the       */
  2105.                         /* shadow objects                             */
  2106.   do i = 1 to words( shadowIndizes )
  2107.     call WriteObjectData word( shadowIndizes, i ), outputFile
  2108.   end /* do i = 1 to words( shadowIndizes )  */
  2109.  
  2110.                         /* write the code to recreate the objects     */
  2111.   call lineOut OutputFile , ,
  2112.    '                                                                        ' crLF ||,
  2113.    '  objects.0 = i                                                         ' crLF ||,
  2114.    '                                                                        ' crLF ||,
  2115.    '                                                                        ' crLF ||,
  2116.    '                        /* now create the objects                     */' crLF ||,
  2117.    '  errorCounter = 0                                                      ' crLF ||,
  2118.    '  okCounter = 0                                                         ' crLF ||,
  2119.    '                                                                        ' crLF ||,
  2120.    '  do i = 1 to objects.0                                                 ' crLF ||,
  2121.    '    say " Creating the object """ || objects.i.__title || """ ..."      ' crLF ||,
  2122.    '    if SysCreateObject( objects.i.__class       ,,                      ' crLF ||,
  2123.    '                        objects.i.__title       ,,                      ' crLF ||,
  2124.    '                        objects.i.__location    ,,                      ' crLF ||,
  2125.    '                        objects.i.__setup       ,,                      ' crLF ||,
  2126.    '                        "UPDATE" ) <> 1 then                            ' crLF ||,
  2127.    '    do                                                                  ' crLF ||,
  2128.    '      errorCounter = errorCounter + 1                                   ' crLF ||,
  2129.    '      say "  *** Warning: Can not create the object """ || ,            ' crLF ||,
  2130.    '          objects.i.__title || """ (Index=" || i || ")!"               ' crLF ||,
  2131.    '    end /* if SysCreateObject( ... */                                   ' crLF ||,
  2132.    '    else                                                                ' crLF ||,
  2133.    '      okCounter = okCounter + 1                                         ' crLF ||,
  2134.    '  end /* do i = 1 to objects.0 */                                       ' crLF ||,
  2135.    '                                                                        ' crLF ||,
  2136.    '  say okCounter || " object(s) created, " || ,                          ' crLF ||,
  2137.    '      errorCounter || " object creation(s) failed."                     ' crLF ||,
  2138.    '                                                                        ' crLF ||,
  2139.    'exit                                                                    ' crLF
  2140.  
  2141.   call stream outputFile, 'c', 'CLOSE'
  2142.  
  2143.   if prog.__QuietMode <> 1 then
  2144.   do
  2145.     call lineOut prog.__STDOUT, 'done.'
  2146.     call LineOUt prog.__STDOUT, '' 
  2147.     call CharOut prog.__STDOUT,  screen.__promptColor || ,
  2148.                                 '┌' || center( '─', prog.__screenCols-2 , '─' ) || '┐'
  2149.     call CharOut prog.__STDOUT, '│ ' || center( 'Check the program ', prog.__screenCols-4 ) || ' │'
  2150.     call CharOut prog.__STDOUT, '│ ' || center(  outputFile , prog.__screenCols-4 ) || ' │'
  2151.     call CharOut prog.__STDOUT, '│ ' || center( 'carefully before using it!', prog.__screenCols-4 ) || ' │'
  2152.     call CharOut prog.__STDOUT, '│ ' || center( '(see WPTOOLS.TXT)', prog.__screenCols-4 ) || ' │'
  2153.     call CharOut prog.__STDOUT, '└' || center( '─', prog.__screenCols-2 , '─' ) || '┘' || ,
  2154.                                 screen.__AttrOff || screen.__normalColor
  2155.     call LineOUt prog.__STDOUT, center( ' ' , prog.__screenCols )
  2156.   end /* if prog.__QuietMode <> 1 then */
  2157.   
  2158. RETURN thisRC
  2159.  
  2160. /* ------------------------------------------------------------------ */
  2161. /* function: write the object data to the REXX program file           */
  2162. /*                                                                    */
  2163. /* call:     WriteObjectData i, outputFile                            */
  2164. /*                                                                    */
  2165. /* where:    i = index in the stem objectStem.                        */
  2166. /*           outputFile = name of the output file                     */
  2167. /*                                                                    */
  2168. /* returns:  nothing                                                  */
  2169. /*                                                                    */
  2170. /*                                                                    */
  2171. WriteObjectData: PROCEDURE expose (exposeList)
  2172.   parse arg i, outputFile .
  2173.  
  2174.   call lineOut outputFile, ''
  2175.   call LineOut outputFile, '  i=i+1;'
  2176.   call LineOut outputFile, '  objects.i.__Title    = "' || ,
  2177.                            CheckString( objectStem.i.__title ) || '"'
  2178.   call LineOut outputFile, '  objects.i.__Class    = "' ||,
  2179.                            CheckString( objectStem.i.__Class ) || '"'
  2180.  
  2181.   call SplitSetupString 50 , objectStem.i.__SetupString
  2182.  
  2183.   if SetupStrStem.0 <> 1 then
  2184.     call LineOut outputFile, '  objects.i.__Setup    = "' ||,
  2185.                              CheckString( SetupStrStem.1 ) || '" ||,'
  2186.   else
  2187.     call LineOut outputFile, '  objects.i.__Setup    = "' || ,
  2188.                              CheckString( SetupStrStem.1 ) || '"'
  2189.  
  2190.   do n = 2 to SetupStrStem.0
  2191.     if n <> SetupStrStem.0 then
  2192.       call LineOut outputFile, '                         "' ||,
  2193.                                CheckString( SetupStrStem.n ) || '" ||,'
  2194.     else
  2195.       call LineOut outputFile, '                         "' || ,
  2196.                                CheckString( SetupStrStem.n ) || '" '
  2197.   end /* do n = 2 to SetupStrStem.0 */
  2198.  
  2199.   call LineOut outputFile, '  objects.i.__location = "' || ,
  2200.                            CheckString( objectStem.i.__location ) || '"'
  2201.  
  2202. RETURN
  2203.  
  2204. /* ------------------------------------------------------------------ */
  2205. /* function: replace all " with "" in a string                        */
  2206. /*                                                                    */
  2207. /* call:     CheckString stringToTest                                 */
  2208. /*                                                                    */
  2209. /* where:    stringToTest - string to test                            */
  2210. /*                                                                    */
  2211. /* returns:  the converted string                                     */
  2212. /*                                                                    */
  2213. /*                                                                    */
  2214. CheckString: PROCEDURE expose (exposeList)
  2215.   parse arg stringToTest
  2216.  
  2217.   i = pos( '"', stringToTest )
  2218.  
  2219.   do while i <> 0
  2220.  
  2221.     stringToTest = insert( '"', stringToTest, i )
  2222.     i = pos( '"', stringToTest, i+2 )
  2223.   end /* do while i <> 0 */
  2224.  
  2225. RETURN stringToTest
  2226.  
  2227. /* ------------------------------------------------------------------ */
  2228. /* function: show the object data                                     */
  2229. /*                                                                    */
  2230. /* call:     ShowObjectData                                           */
  2231. /*                                                                    */
  2232. /* where:    -                                                        */
  2233. /*                                                                    */
  2234. /* returns:  nothing                                                  */
  2235. /*                                                                    */
  2236. /*                                                                    */
  2237. ShowObjectData: PROCEDURE expose (exposeList)
  2238.  
  2239.  if prog.__QuietMode <> 1 then
  2240.    call CharOut prog.__STDOUT , ' Creating the object list ...'
  2241.  
  2242.   prog.__tQuietMode = prog.__QuietMode
  2243.  
  2244.   if prog.__LogFile <> 'NUL' then
  2245.   do
  2246.                         /* do not write the data to the screen if     */
  2247.                         /* the logfile parameter was entered          */
  2248.     prog.__QuietMode = 1
  2249.   end /* if prog.__LogFile <> 'NUL' then */
  2250.  
  2251.   call log 'Data of the objects found'
  2252.   call log '-------------------------'
  2253.   call log ''
  2254.  
  2255.   indentValue = 0
  2256.  
  2257. /* ??? DEBUG ??? debug code to test the routine SplitSetupString
  2258.  
  2259.   do i = 1 to objectStem.0
  2260.     SetupStringPrefix = copies( ' ', indentValue ) || 'SetupString: '
  2261.     SetupStringPartLength = prog.__ScreenCols - length( SetupStringPrefix ) -2
  2262.  
  2263.     call SplitSetupString SetupStringPartLength , objectStem.i.__SetupString
  2264.     testString = ''
  2265.     do k = 1 to SetupStrStem.0
  2266.       testString = testString || SetupStrStem.k
  2267.     end
  2268.     if testString = objectStem.i.__SetupString  then
  2269.       call log 'ok'
  2270.     else
  2271.     do
  2272.       call log 'error: ' || objectStem.i.__Title
  2273.       call log '       ' || objectStem.i.__SetupString
  2274.       call log '       ' || testString
  2275.     end
  2276.   end
  2277. ??? DEBUG end of debug code */
  2278.  
  2279.   do i = 1 to objectStem.0
  2280.                         /* calculate the indent for the description   */
  2281.                         /* of this object                             */
  2282.     if objectStem.i.__FolderName <> '' then
  2283.       indentValue = CalculateIndentValue( objectStem.i.__FolderName )
  2284.  
  2285.     call log ''
  2286.  
  2287.     call log copies( ' ', indentValue ) || 'Title:       ' || ,
  2288.              objectStem.i.__Title
  2289.     call log copies( ' ', indentValue ) || 'Class:       ' || ,
  2290.              objectStem.i.__Class
  2291.  
  2292.     SetupStringPrefix = copies( ' ', indentValue ) || 'SetupString: '
  2293.     SetupStringPartLength = prog.__ScreenCols - length( SetupStringPrefix ) -2
  2294.  
  2295.     call SplitSetupString SetupStringPartLength , objectStem.i.__SetupString
  2296.     call log SetupStringPrefix || SetupStrStem.1
  2297.     do k = 2 to SetupStrStem.0
  2298.       call log copies( ' ', length( SetupStringPrefix ) ) || SetupStrStem.k
  2299.     end /* do k = 2 to SetupStrStem.0 */
  2300.  
  2301.     call log copies( ' ', indentValue ) ||   'Location:    ' || ,
  2302.              objectStem.i.__location
  2303.  
  2304.     if objectStem.i.__FileName <> '' then
  2305.       call log copies( ' ', indentValue ) || 'Filename:    ' || ,
  2306.              objectStem.i.__FileName
  2307.  
  2308.     if objectStem.i.__FolderName <> '' then
  2309.     do
  2310.       call log copies( ' ', indentValue ) || 'DirName:     ' || ,
  2311.              objectStem.i.__FolderName
  2312.  
  2313.                         /* calculate the indent for the description   */
  2314.                         /* of the next objects                        */
  2315.       indentValue = CalculateIndentValue( objectStem.i.__FolderName ) +2
  2316.     end /* if */
  2317.  
  2318.   end /* do i = 1 to objectStem.0 */
  2319.  
  2320.   prog.__QuietMode = prog.__tQuietMode
  2321.  
  2322.   if prog.__QuietMode <> 1 then
  2323.     call LineOut prog.__STDOUT , 'done.'
  2324.  
  2325. RETURN
  2326.  
  2327. /* ------------------------------------------------------------------ */
  2328. /* function: show the statistic data                                  */
  2329. /*                                                                    */
  2330. /* call:     ShowStatisticData                                        */
  2331. /*                                                                    */
  2332. /* where:    -                                                        */
  2333. /*                                                                    */
  2334. /* returns:  nothing                                                  */
  2335. /*                                                                    */
  2336. /*                                                                    */
  2337. ShowStatisticData:
  2338.  
  2339.   if prog.__QuietMode <> 1 then
  2340.     call CharOut prog.__STDOUT , ' Creating the statistics ...'
  2341.  
  2342.   prog.__tQuietMode = prog.__QuietMode
  2343.  
  2344.   if prog.__LogFile <> 'NUL' then
  2345.   do
  2346.                         /* do not write the data to the screen if     */
  2347.                         /* the logfile parameter was entered          */
  2348.     prog.__QuietMode = 1
  2349.   end /* if prog.__LogFile <> 'NUL' then */
  2350.  
  2351.   call log ''
  2352.   call log 'And now some statistics ...'
  2353.   call log ''
  2354.  
  2355.   if processSubFolders = 1 then
  2356.   do
  2357.     call log 'There are ' || ,
  2358.              AddColor1( , folderStruc.0-1 ) || ,
  2359.              ' sub folder(s) in the folder ' || ,
  2360.              AddColor1( '"', folderStruc.1 ) || ,
  2361.              ' and its sub folders.'
  2362.     call log 'The max. folder depth is ' || ,
  2363.              AddColor1( , statistics.__MaxFolderDepth ) || ,
  2364.              '.'
  2365.   end /* if processSubFolders = 1 then */
  2366.  
  2367.   call log 'There are (at least) ' || ,
  2368.            AddColor1( , objectStem.0-1 ) || ,
  2369.            ' object(s) in the folder(s) (incl. ' || ,
  2370.            AddColor1( , statistics.__NotVisibleObjects ) || ,
  2371.            ' not visible object(s)).'
  2372.  
  2373.   call log AddColor1( , statistics.__TemplateObjects ) || ,
  2374.            ' object(s) are templates.'
  2375.  
  2376.   call log AddColor1( , statistics.__ObjectsWithID ) ||,
  2377.            ' object(s) have an object ID, ' || ,
  2378.            AddColor1( , statistics.__ObjectsWithOutID ) ||,
  2379.            ' object(s) have no object ID.'
  2380.  
  2381.   call log ''
  2382.  
  2383.   call log '                        No. of                                          '
  2384.   call log 'ObjectClass          objects found     DLL                              '
  2385.   call log '------------------------------------------------------------------------'
  2386.  
  2387.   do i = 1 to words( objectCountStem.__ClassNames )
  2388.     curClassName = strip( word( objectCountStem.__ClassNames, i ) )
  2389.     call log left( curClassName, 25 ) ||,
  2390.          right( value( 'objectCountStem.' || curClassName ), 4 ) || ,
  2391.          '          ' || ,
  2392.          GetDllName( curClassName )
  2393.   end /* do i = 1 to ... */
  2394.  
  2395.   call log ''
  2396.  
  2397.   call log 'progType                      No. of objects found'
  2398.   call log '--------------------------------------------------'
  2399.  
  2400.   do i = 1 to words( progTypes.__UsedTypes )
  2401.     curProgType = strip( word( progTypes.__UsedTypes, i ) )
  2402.     call log left( curProgType, 30 ) || ,
  2403.              right( value( 'progTypes.' || curProgType ), 10 )
  2404.   end /* do i = 1 to ... */
  2405.  
  2406.   thisRC = 0
  2407.  
  2408.                         /* maximum length of an object ID             */
  2409.   maxObjectIDLength = 0
  2410.  
  2411.                         /* prepare the arrays for the shell sort      */
  2412.                         /* and get the maximum length of the object   */
  2413.                         /* IDs                                        */
  2414.   do i = 1 to statistics.__ObjectIDs.0
  2415.     key.i = statistics.__ObjectIDs.i
  2416.     ind.i = i
  2417.     maxObjectIDLength = max( maxObjectIDLength, length( statistics.__ObjectIDs.i ) )
  2418.   end /* do i = 1 to key.0 */
  2419.   key.0 = statistics.__ObjectIDs.0
  2420.  
  2421.                         /* sort the stem with the object IDs          */
  2422.   call ShellSort 2, key.0
  2423.  
  2424.                         /* calculate the number of object IDs per     */
  2425.                         /* line for the output                        */
  2426.   objectIDsPerLine = trunc( (prog.__ScreenCols-1) / (maxObjectIDLength+2) )
  2427.   if objectIDsPerLine = 0 then
  2428.     objectIDsPerLine = 1
  2429.  
  2430.                         /* calculate the field length for one object  */
  2431.                         /* ID in the output                           */
  2432.   fieldLength = trunc( (prog.__ScreenCols-1) / (objectIDsPerLine) )
  2433.  
  2434.   call log ''
  2435.   call log 'Used object IDs:'
  2436.   call log '----------------'
  2437.  
  2438.  
  2439.   fieldCount = 0        /* number of object IDs already in the        */
  2440.                         /* current line                               */
  2441.  
  2442.   thisIDLine = ''       /* variable for the output                    */
  2443.  
  2444.   do i = 1 to key.0
  2445.     curIndex = ind.i
  2446.  
  2447.     fieldCount = fieldCount + 1
  2448.     if fieldCount >= objectIDsPerLine then
  2449.     do
  2450.       call log thisIDLine
  2451.       fieldCount = 0
  2452.       thisIDLIne = ''
  2453.     end /* if */
  2454.  
  2455.     thisIDLine = thisIDLIne || left( value( 'key.' || curIndex ), fieldLength )
  2456.  
  2457.   end /* do i = 1 to key.0 */
  2458.  
  2459.   if thisIDLine <> '' then
  2460.     call log thisIDLine
  2461.  
  2462.   prog.__QuietMode = prog.__tQuietMode
  2463.  
  2464.   if prog.__QuietMode <> 1 then
  2465.     call LineOut prog.__STDOUT , 'done.'
  2466.  
  2467. RETURN
  2468.  
  2469. /* ------------------------------------------------------------------ */
  2470. /* function: get the name of the dll containing a WPS class           */
  2471. /*                                                                    */
  2472. /* call:     GetDLLName thisClassName                                 */
  2473. /*                                                                    */
  2474. /* where:    thisClassName     - name of the WPS class                */
  2475. /*                                                                    */
  2476. /* returns:  name of the DLL or '' if not found                       */
  2477. /*                                                                    */
  2478. /*                                                                    */
  2479. GetDLLName: PROCEDURE expose (exposeList)
  2480.   parse arg thisClassName .
  2481.  
  2482.   thisDLLName = ''
  2483.  
  2484.   if symbol( 'classList.0' ) <> 'VAR' then
  2485.   do
  2486.                         /* get the list of all registered WPS classes */
  2487.                         /* do this only once!                         */
  2488.     call sysQueryClassList 'tempClassList.'
  2489.  
  2490.     do i = 1 to tempClassList.0
  2491.       parse var tempClassList.i curClassName curDllName
  2492.  
  2493.       classList.i.__ClassName = strip( curClassName )
  2494.       classList.i.__DLLName = strip( curDllName )
  2495.  
  2496.     end /* do i = 1 to tempClassList.0 */
  2497.  
  2498.     classList.0 = tempClassList.0
  2499.  
  2500.   end /* if symbol( 'classList.0' ) <> 'VAR' then */
  2501.  
  2502.   do i = 1 to classList.0 until thisDLLName <> ''
  2503.     if classList.i.__ClassName = thisClassName then
  2504.       thisDLLName = classList.i.__DLLName
  2505.   end /* do i = 1 to classList.0 */
  2506.  
  2507. RETURN thisDllName
  2508.  
  2509. /* ------------------------------------------------------------------ */
  2510. /* function: get the data of all objects in a folder                  */
  2511. /*                                                                    */
  2512. /* call:     ProcessFolder thisFolder                                 */
  2513. /*                                                                    */
  2514. /* where:    thisFolder        - fully qualified name of the folder   */
  2515. /*           IncludeSubFolders - 1: also get the object data for      */
  2516. /*                               sub folders                          */
  2517. /*                                                                    */
  2518. /* returns:  1 - okay                                                 */
  2519. /*           else error                                               */
  2520. /*                                                                    */
  2521. /* note:     the object data is saved in the stem objectStem., the    */
  2522. /*           data of the stem objectCountStem. is also updated.       */
  2523. /*                                                                    */
  2524. ProcessFolder: PROCEDURE expose (exposeList)
  2525.   parse arg '"' thisFolder '"' , IncludeSubFolders
  2526.   thisRC = 0
  2527.  
  2528.                         /* first get the object data of the folder    */
  2529.   folderIndex = GetObjectSettings( '"' || thisFolder || '"' )
  2530.   if folderIndex = 0 then
  2531.     call ShowWarning ,
  2532.          'Error detecting the data of the folder "' || ,
  2533.           thisFolder || '"'
  2534.   else
  2535.   do
  2536.                         /* save the folder name                       */
  2537.     objectStem.folderIndex.__FolderName = thisFolder
  2538.  
  2539.                      /* get the data for all objects in the folder    */
  2540.     call WPToolsFolderContent thisFolder, "localList."
  2541.  
  2542.     if datatype( localList.0, 'NUM' ) = 1 then
  2543.     do k = 1 to localList.0
  2544.       if GetObjectSettings( '"' || localList.k || '"' ) = 0 then
  2545.         call ShowWarning ,
  2546.              'Error detecting the data of the object "' || localList.k || '"'
  2547.     end /* do k = 1 to localList.0 */
  2548.  
  2549.                         /* get the files in this folder               */
  2550.     rc = SysFileTree( thisFolder || '\*.*', 'fileObjects.', 'FO' )
  2551.     if rc <> 0 then
  2552.       call ShowWarning ,
  2553.         'Error ' || rc || ' detecting the files in the folder "' || ,
  2554.         thisFolder || '"'
  2555.     else
  2556.     do
  2557.       do k = 1 to fileObjects.0
  2558.         j = GetObjectSettings( '"' || fileObjects.k || '"' )
  2559.         if j = 0 then
  2560.           call ShowWarning ,
  2561.                'Error detecting the data of the object "' || ,
  2562.                fileObjects.k || '"'
  2563.         else
  2564.           objectStem.j.__FileName = fileObjects.k
  2565.       end /* do k = 1 to fileObjects.0 */
  2566.     end /* end */
  2567.  
  2568.                         /* get the sub folder in this folder          */
  2569.     if IncludeSubFolders = 1 then
  2570.     do
  2571.       rc = SysFileTree( thisFolder || '\*.*', 'dirObjects.', 'DO' )
  2572.       if rc <> 0 then
  2573.         call ShowWarning ,
  2574.           'Error ' || rc || ' detecting the files in the folder "' || ,
  2575.           thisFolder || '"'
  2576.       else
  2577.       do
  2578.         do k = 1 to dirObjects.0
  2579.           j = GetObjectSettings( '"' || dirObjects.k || '"' )
  2580.           if j = 0 then
  2581.             call ShowWarning ,
  2582.                  'Error detecting the data of the folder "' || ,
  2583.                  dirObjects.k || '"'
  2584.           else
  2585.             objectStem.j.__FolderName = dirObjects.k
  2586.         end /* do k = 1 to dirObjects.0 */
  2587.       end /* end */
  2588.     end /* if IncludeSubFolders = 1 then */
  2589.  
  2590.   end /* else */
  2591.  
  2592.   thisRC = 1
  2593. RETURN thisRC
  2594.  
  2595. /* ------------------------------------------------------------------ */
  2596. /* function: get the data of an object                                */
  2597. /*                                                                    */
  2598. /* call:     GetObjectSettings "thisObject"                           */
  2599. /*                                                                    */
  2600. /* where:    thisObject = id of the object                            */
  2601. /*                                                                    */
  2602. /* returns:  0 - error,                                               */
  2603. /*           n - okay, object data saved in the stem objectStem.      */
  2604. /*               n is the index number for the stem objectStem.       */
  2605. /*           the data of the stem objectCountStem. is also updated.   */
  2606. /*                                                                    */
  2607. GetObjectSettings: PROCEDURE expose  (exposeList)
  2608.   parse arg '"' thisObjectID '"'
  2609.  
  2610.   thisRC = WPToolsQueryObject( thisObjectID, "szClass",,
  2611.                                                "szTitle",,
  2612.                                              "szSetupString",,
  2613.                                              "szLocation" )
  2614.   if thisRC = 1 then
  2615.   do
  2616.     j = objectStem.0+1
  2617.     objectStem.j.__class = szClass
  2618.     objectStem.j.__title = szTitle
  2619.     objectStem.j.__SetupString = szSetupString
  2620.     objectStem.j.__Location = szLocation
  2621.     objectStem.0 = j
  2622.  
  2623.     thisRC = j
  2624.  
  2625.     if value( 'objectCountStem.' || szClass ) = 0 then
  2626.       objectCountStem.__ClassNames = objectCountStem.__ClassNames szClass
  2627.  
  2628.     interpret 'objectCountStem.' || szClass || ' = objectCountStem.' || szClass || '+1'
  2629.  
  2630.                         /* collect the statistic data                 */
  2631.     testString = ';' || translate( szSetupString ) || ';'
  2632.  
  2633.     i1 = pos( ';PROGTYPE=', testString )
  2634.     if i1 <> 0 then
  2635.     do
  2636.       i2 = pos( ';', testString, i1+1 )
  2637.       curProgType = substr( szSetupString, i1+9, i2-i1-10 )
  2638.  
  2639.       if value( 'progTypes.' || curProgType ) = 0 then
  2640.         progTypes.__UsedTypes = progTypes.__UsedTypes curProgType
  2641.  
  2642.       interpret 'progTypes.' || curProgType || ' = progTypes.' || curProgType || '+1'
  2643.  
  2644.     end /* if i1 <> 0 then */
  2645.  
  2646.     if pos( ';NOTVISIBLE=YES', testString ) <> 0 then
  2647.       statistics.__NotVisibleObjects = statistics.__NotVisibleObjects + 1
  2648.  
  2649.     if pos( 'TEMPLATE=YES', testString ) <> 0 then
  2650.       statistics.__templateObjects = statistics.__templateObjects + 1
  2651.  
  2652.     i1 = pos( ';OBJECTID=', testString )
  2653.     if i1 <> 0 then
  2654.     do
  2655.       i2 = pos( ';', testString, i1+1 )
  2656.       curObjectID = substr( szSetupString, i1+9, i2-i1-10 )
  2657.  
  2658.       j = statistics.__ObjectIDs.0 +1
  2659.       statistics.__ObjectIDs.j = curObjectID
  2660.       statistics.__ObjectIDS.0 = j
  2661.  
  2662.       statistics.__ObjectsWithID = statistics.__ObjectsWithID + 1
  2663.     end /* if i1 <> 0 then */
  2664.     else
  2665.       statistics.__ObjectsWithOutID = statistics.__ObjectsWithOutID + 1
  2666.  
  2667.   end /* if thisRC = 1 */
  2668.  
  2669. RETURN thisRC
  2670.  
  2671. /* ------------------------------------------------------------------ */
  2672. /* function: calculate the value for the indent                       */
  2673. /*                                                                    */
  2674. /* call:     CalculateIndentValue thisFolder                          */
  2675. /*                                                                    */
  2676. /* where:    thisFolder        - fully qualified name of the folder   */
  2677. /*                                                                    */
  2678. /* returns:  no. of cols for the indent (= number of '\' in the       */
  2679. /*           folder name -1 *2 )                                      */
  2680. /*                                                                    */
  2681. /*                                                                    */
  2682. CalculateIndentValue: PROCEDURE expose (exposeList)
  2683.   parse arg thisFolder
  2684.  
  2685.   IndentValue = 0
  2686.  
  2687.   startPosition = 0
  2688.  
  2689.   do forever
  2690.     startPosition = pos( '\', thisFolder, startPosition+1 )
  2691.     if startPosition = 0 then
  2692.       leave
  2693.     else
  2694.       IndentValue = IndentValue + 1
  2695.   end /* do forever */
  2696.  
  2697.   statistics.__MaxFolderDepth = max( statistics.__MaxFolderDepth, indentValue )
  2698.  
  2699.   IndentValue = ( IndentValue -1 ) * 2
  2700.  
  2701.   if IndentValue < 0 then
  2702.     IndentValue = 0
  2703.  
  2704. RETURN IndentValue
  2705.  
  2706. /* ------------------------------------------------------------------ */
  2707. /* function: get the desktop directory                                */
  2708. /*                                                                    */
  2709. /* call:     GetDesktopDirectory                                      */
  2710. /*                                                                    */
  2711. /* where:    -                                                        */
  2712. /*                                                                    */
  2713. /* returns:  the fully qualified name of the desktop directory        */
  2714. /*           or '' in case of an error                                */
  2715. /*                                                                    */
  2716.  
  2717. /**********************************************************************/
  2718. /*                                                                    */
  2719. /* GETDESK.CMD                                                        */
  2720. /*                                                                    */
  2721. /* Version: 1.2                                                       */
  2722. /*                                                                    */
  2723. /* Written by:  Georg Haschek (haschek at vnet.ibm.com)               */
  2724. /*                                                                    */
  2725. /* Description: Return the desktop's directory name to the caller.    */
  2726. /*                                                                    */
  2727. /* captured from a message in a public CompuServe forum               */
  2728. /**********************************************************************/
  2729.  
  2730. /**************/
  2731. /* Initialize */
  2732. /**************/
  2733.  
  2734. GetDesktopDirectory: PROCEDURE expose (exposeList)
  2735.   Return Getpath( Substr( SysIni( "USER",,
  2736.                   "PM_Workplace:Location", "<WP_DESKTOP>" ),1,2 ) )
  2737.  
  2738. /***********************************************/
  2739. /* Loop through the nodes to get the path info */
  2740. /***********************************************/
  2741. Getpath: Procedure Expose nodes. (exposeList)
  2742.   If Getnodes( ) <> 0 Then
  2743.     Return ""
  2744.  
  2745.   gpinode = Arg( 1 )
  2746.  
  2747.   If nodes.gpinode = "" Then
  2748.     Return ""
  2749.  
  2750.   gp = Substr( nodes.gpinode,33,Length( nodes.gpinode )-33 )
  2751.   gpparent = Substr( nodes.gpinode,9,2 )
  2752.  
  2753.   If gpparent <> "0000"x Then
  2754.   Do
  2755.     Do Until gpparent = "0000"x
  2756.       gp = Substr( nodes.gpparent,33,Length( nodes.gpparent )-33 ) || ,
  2757.            "\" || gp
  2758.       gpparent = Substr( nodes.gpparent,9,2 )
  2759.     End
  2760.   End
  2761. Return gp
  2762.  
  2763. /*****************/
  2764. /* Get the nodes */
  2765. /*****************/
  2766. Getnodes: Procedure Expose nodes. (exposeList)
  2767.   handlesapp = SysIni( "SYSTEM","PM_Workplace:ActiveHandles",,
  2768.                        "HandlesAppName" )
  2769.  
  2770.   If handlesapp = "ERROR:" Then
  2771.     handlesapp = "PM_Workplace:Handles"
  2772.  
  2773.   block1 = ""
  2774.   Do i = 1 to 999
  2775.     block = SysIni( "SYSTEM", handlesapp, "BLOCK" || i )
  2776.     If block = "ERROR:" Then
  2777.     Do
  2778.       If i = 1 Then
  2779.       Do
  2780.         call ShowWarning ,
  2781.                "Unable to locate the NODE table, you are probably",
  2782.                "using OS/2 2.0 without the Service Pack."
  2783.         Return 1
  2784.       End
  2785.       Leave
  2786.     End
  2787.     block1 = block1 || block
  2788.   End
  2789.  
  2790.   l = 0
  2791.   nodes. = ""
  2792.   Do Until l >= Length( block1 )
  2793.     If Substr( block1,l+5,4 ) = "DRIV" Then
  2794.     Do
  2795.       xl = Pos( "00"x || "NODE" || "01"x, block1,l+5 )-l
  2796.       If xl <= 0 Then
  2797.         Leave
  2798.       l = l + xl
  2799.       Iterate
  2800.     End
  2801.     Else
  2802.     Do
  2803.       If Substr( block1,l+1,4 ) = "DRIV" Then
  2804.       Do
  2805.         xl = Pos( "00"x || "NODE" || "01"x, block1,l+1 )-l
  2806.         If xl <= 0 Then
  2807.           Leave
  2808.         l = l + xl
  2809.         Iterate
  2810.       End
  2811.       Else
  2812.       Do
  2813.         data = Substr( block1,l+1,32 )
  2814.         xl = C2D( Substr( block1,l+31,1 ) )
  2815.         If xl <= 0 Then
  2816.           Leave
  2817.         data = data || Substr( block1,l+33,xl+1 )
  2818.         l = l + Length( data )
  2819.       End
  2820.     End
  2821.     xnode = Substr( data,7,2 )
  2822.     nodes.xnode = data
  2823.   End
  2824. Return 0
  2825.  
  2826. /* ------------------------------------------------------------------ */
  2827. /*-function: sort a stem                                              */
  2828. /*                                                                    */
  2829. /*-call:     ShellSort low, high                                      */
  2830. /*                                                                    */
  2831. /*-where:    see below                                                */
  2832. /*                                                                    */
  2833. /*-returns:  ''                                                       */
  2834. /*                                                                    */
  2835. /*                                                                    */
  2836. /* Routine SHELLSORT.                                                 */
  2837. /*                                                                    */
  2838. /* This REXX subroutine can be used to perform a generic sort. It has */
  2839. /* been written in a generic fashion to make it as easy as possible   */
  2840. /* to plug it into the EXEC of your choice. The algorithm used is the */
  2841. /* fastest non-recursive one that I know of for lists in random       */
  2842. /* sequence, but if you've got one that's faster, then I challenge    */
  2843. /* you to produce an equivalent of this routine using your algorithm. */
  2844. /*                                                                    */
  2845. /* Before calling this procedure you need to have set up two arrays,  */
  2846. /* key. and ind., containing, respectively, the key field for         */
  2847. /* comparison purposes, and an index (or pointer) to each element.    */
  2848. /*                                                                    */
  2849. /* The subroutine takes two numeric arguments representing the first  */
  2850. /* and last elements to be sorted, and returns ind. as a pointer list */
  2851. /* in ascending order. To change it to sort into descending order all */
  2852. /* you need do is change the line that compares key.kind to tempdat   */
  2853. /* so that the test is inverted (ie. > becomes <). Alternatively you  */
  2854. /* could process the index in reverse order (see below).              */
  2855. /*                                                                    */
  2856. /* Thus if you had done a CP QUERY RDR ALL into a variable RDRLIST.   */
  2857. /* you would code the following to sort it into file name order:      */
  2858. /*                                                                    */
  2859. /* do i=1 to rdrlist.0                                                */
  2860. /*    key.i=substr(rdrlist.i,54,8)                                    */
  2861. /*    ind.i=i                                                         */
  2862. /* end                                                                */
  2863. /*                                                                    */
  2864. /* call shellsort 2,rdrlist.0                                         */
  2865. /*                                                                    */
  2866. /* Note that the first index is 2 because rdrlist.1 is a header line. */
  2867. /*                                                                    */
  2868. /* To print the list in sorted order you would then code:             */
  2869. /*                                                                    */
  2870. /* do i=1 to rdrlist.0                                                */
  2871. /*    rind=ind.i                                                      */
  2872. /*    say rdrlist.rind                                                */
  2873. /* end                                                                */
  2874. /*                                                                    */
  2875. /* Note the use of the pointer. Unfortunately it is not possible to   */
  2876. /* code rdrlist.(ind.i) to get the same effect in a single statement. */
  2877. /* To display items in descending order you simply reverse the loop,  */
  2878. /* do i=rdrlist.0 to 1 by -1, although this would display the header  */
  2879. /* at the end, in this instance!                                      */
  2880. /*                                                                    */
  2881. /**********************************************************************/
  2882. /*                                                                    */
  2883. /*  VER   TIME   DATE    BY   NARRATIVE                               */
  2884. /*  1.0  15:22 90/02/20 SJP - Original version. Generic sort routine  */
  2885. /*                            using Shell algorithm.                  */
  2886. /*  1.1  10:13 90/12/07 SJP - Added check for first element number    */
  2887. /*                            not being less than last element        */
  2888. /*                            number.                                 */
  2889. /*  1.2  09:49 92/02/19 SJP - Moved procedure statement for VM/ESA.   */
  2890. /*  1.3  10:51 93/08/27 SJP - Tidied up and corrected documentation.  */
  2891. /*                                                                    */
  2892. /**********************************************************************/
  2893. shellsort: PROCEDURE expose (exposeList) key. ind.
  2894.   trace o
  2895.  
  2896.               /* Check that there are at least two elements to sort   */
  2897.   parse arg low, high
  2898.   if low >= high then
  2899.     return
  2900.  
  2901.               /* Calculate an optimal initial gap size                */
  2902.   gap = 1
  2903.   do while gap < (high-low)+1
  2904.      gap = gap*3
  2905.   end
  2906.  
  2907.               /* Basically we sort the elements 'gap' elements        */
  2908.               /* apart, gradually reducing 'gap' until it is one,     */
  2909.               /* at which point the list will be fully sorted.        */
  2910.   do until gap = 1
  2911.      gap=gap/3
  2912.      do i=(gap+low) to high
  2913.         j=i
  2914.         tempind=ind.j
  2915.         tempdat=key.tempind
  2916.         k=j-gap
  2917.         kind=ind.k
  2918.         do while key.kind > tempdat
  2919.            ind.j=ind.k
  2920.            j=k
  2921.            k=j-gap
  2922.            if k < low then leave
  2923.            kind=ind.k
  2924.         end
  2925.         ind.j=tempind
  2926.      end
  2927.   end
  2928. RETURN
  2929.  
  2930. /* ------------------------------------------------------------------ */
  2931. /*-function: DeRegister the functions from the DLL WPTOOLS            */
  2932. /*                                                                    */
  2933. /*-call:     called by the runtime system                             */
  2934. /*                                                                    */
  2935. /*-where:    -                                                        */
  2936. /*                                                                    */
  2937. /*-returns:  ''                                                       */
  2938. /*                                                                    */
  2939. /*                                                                    */
  2940. DeRegisterWPTools: PROCEDURE expose (exposeList)
  2941.   call rxFuncDrop 'WPToolsLoadFunc'
  2942.   call rxFuncDrop 'WPToolsQueryObject'
  2943.   call rxFuncDrop 'WPToolsFolderContent'
  2944. RETURN ''
  2945.  
  2946. /* ------------------------------------------------------------------ */
  2947. /* Function: split a setup string into parts with a maximum length    */
  2948. /*                                                                    */
  2949. /* call:     SplitSetupString length , setupString                    */
  2950. /*                                                                    */
  2951. /* where:    length - max. length for the parts                       */
  2952. /*           setupString - setup String                               */
  2953. /*                                                                    */
  2954. /* returns:  1                                                        */
  2955. /*                                                                    */
  2956. /*           SetupStrStem.0 - no. of parts                            */
  2957. /*           SetupStrStem.# - part 1 to n                             */
  2958. /*                                                                    */
  2959. /* Note:     The setup string is splitted at semicolons (;). If a     */
  2960. /*           part of the setup string is to long, it is splitted at   */
  2961. /*           commas (,).                                              */
  2962. /*           Setupstrings (and parts of them) without a semikolon and */
  2963. /*           a comma are not splitted.                                */
  2964. /*                                                                    */
  2965. SplitSetupString: PROCEDURE expose (exposeList)
  2966.   parse arg thisLength, setupString
  2967.  
  2968.   SetupStrStem. = ''
  2969.   SetupStrStem.0 = 0
  2970.   j = 1
  2971.  
  2972.   do until setupString = ''
  2973.  
  2974.     parse var setupString curPart ';' setupString
  2975.  
  2976.     select
  2977.       when length( curPart ) >= thisLength then
  2978.       do
  2979.  
  2980.         if length( SetupStrStem.j ) <> 0 then
  2981.           j = j + 1
  2982.  
  2983.         curPart = curPart || ';'
  2984.  
  2985.         do until curPart = ''
  2986.           parse var curPart curTPart ',' curPart
  2987.  
  2988.           if ( length( SetupStrStem.j ) + length( curTPart ) + 1 >= thisLength ) & ,
  2989.              length( SetupStrStem.j ) <> 0 then
  2990.             j = j +1
  2991.  
  2992.           if curPart = '' then
  2993.             SetupStrStem.j = SetupStrStem.j || curTPart
  2994.           else
  2995.             SetupStrStem.j = SetupStrStem.j || curTPart || ','
  2996.  
  2997.         end /* until curPart = '' */
  2998.  
  2999.       end /* when */
  3000.  
  3001.       when length( SetupStrStem.j ) + 1 + length( curPart ) > thisLength then
  3002.       do
  3003.         j = j + 1
  3004.         SetupStrStem.j = curPart || ';'
  3005.       end /* when */
  3006.  
  3007.       otherwise
  3008.       do
  3009.         SetupStrStem.j = SetupStrStem.j || curPart || ';'
  3010.       end /* otherwise */
  3011.  
  3012.     end /* select */
  3013.   end /* do until setupString = '' */
  3014.  
  3015.   setupStrStem.0 = j
  3016.  
  3017. RETURN 1
  3018.  
  3019. /* ------------------------------------------------------------------ */
  3020. /* Function: create a backup of a file                                */
  3021. /*                                                                    */
  3022. /* call:     CreateBackupFile fileToBackup                            */
  3023. /*                                                                    */
  3024. /* where:    fileToBackup = name of the file to backup                */
  3025. /*                                                                    */
  3026. /* returns:  nothing                                                  */
  3027. /*                                                                    */
  3028. CreateBackupFile: PROCEDURE EXPOSE (exposeList)
  3029.   parse arg cbf.oldfileName
  3030.  
  3031.   cbf.i = lastpos( '.', cbf.oldFileName )
  3032.   if cbf.i <> 0 then
  3033.     cbf.testFileName = substr( cbf.oldFileName, 1, cbf.i-1 )
  3034.   else
  3035.     cbf.testFileName = cbf.oldFileName
  3036.  
  3037.   do cbf.index=0 to 999
  3038.     cbf.newFileName = cbf.testFileName || '.' || copies( '0', 3 - LENGTH( cbf.index ) ) || cbf.index
  3039.     if stream( cbf.newFileName,'c', 'QUERY EXISTS' ) = '' then
  3040.       leave
  3041.     cbf.newFileName = ''
  3042.   end /* do cbf.index=0 to 999 */
  3043.  
  3044.   if cbf.newFilename = '' then
  3045.   do
  3046.                                 /* no possible file name found        */
  3047.     call ShowError 3,,
  3048.          'Can not find a name for the backup of the file "' || ,
  3049.          cbf.oldfilename || '"'
  3050.  
  3051.   end /* if cbf.newFilename then */
  3052.   else
  3053.   do
  3054.                                 /* create the backup                  */
  3055.     '@copy ' cbf.oldFileName cbf.newFileName '/V 2>NUL 1>NUL'
  3056.     if rc <> 0 & rc <> "RC" then
  3057.       call ShowError 3 ,,
  3058.            'OS Error ' || rc || ' copying the file "' || ,
  3059.            cbf.oldfilename ||,
  3060.            '" to "' || ,
  3061.            cbf.NewFileName || ,
  3062.            '"'
  3063.   end /* else */
  3064.  
  3065.   drop cbf.
  3066. RETURN
  3067.  
  3068.  
  3069. /* ------------------------------------------------------------------ */
  3070. /* Function: add quote chars and color codes to a string              */
  3071. /*                                                                    */
  3072. /* call:     AddColor1( quoteChar ,myString )                         */
  3073. /*                                                                    */
  3074. /* where:    quoteChar - leading and trailing character for the       */
  3075. /*                       converted string (may be ommited)            */
  3076. /*           myString - string to convert                             */
  3077. /*                                                                    */
  3078. /* returns:  converted string                                         */
  3079. /*                                                                    */
  3080. AddColor1: PROCEDURE expose (exposeList)
  3081.   parse arg quoteChar, myString
  3082.  
  3083. return quoteChar || screen.__fgYellow || screen.__highlight || ,
  3084.        myString || ,
  3085.        screen.__AttrOff || quoteChar
  3086.  
  3087. /* ------------------------------------------------------------------ */
  3088. /*-function: Show the invocation syntax                               */
  3089. /*                                                                    */
  3090. /*-call:     called by the runtime system with                        */
  3091. /*           => call ShowUsage <=                                     */
  3092. /*                                                                    */
  3093. /*-where:    -                                                        */
  3094. /*                                                                    */
  3095. /*-returns:  ''                                                       */
  3096. /*                                                                    */
  3097. ShowUsage: PROCEDURE expose (exposeList)
  3098.   crLF = '0D0A'x
  3099.   
  3100.   call log ' Usage: ' || prog.__name || ' {!|{!}startFolder}'   crLF ,
  3101.            '       {/L:logfile}'                                crLF ,
  3102.            '       {/REXX{=file}} {/NOREXX} '                   crLF ,
  3103.            '       {/STAT} {/NOSTAT}'                           crLF ,
  3104.            '       {/LIST} {/NOLIST}'                           crLF ,
  3105.            '       {/Silent} {/NoAnsi} {/NoSound}'              crLF ,
  3106.            '       {/H}'
  3107. RETURN ''
  3108.  
  3109. /***        End of Part 4 of the source code of TEMPLATE.CMD        ***/
  3110.  
  3111. /**********************************************************************/
  3112.  
  3113.