home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 3 Comm / 03-Comm.zip / cisipf.zip / CIS2IPF.CMD
OS/2 REXX Batch file  |  1994-09-04  |  36KB  |  1,115 lines

  1. /*
  2. Program:         CIS2IPF
  3. Date:            22-Jul-1994
  4. Original Author: Craig Schneiderwent
  5.                  [CompuServe: 74631,165]
  6.                  [Internet: 74631.165@compuserve.com]
  7. Purpose:         To reformat Golden CommPass message files with IPF tags.  The
  8.                  output file can be compiled into an INF file.
  9. Syntax:          Run without any parameters and the proper syntax will be shown.
  10. Return Codes:    0 - Normal EOJ
  11.                  1 - Syntax error
  12.                  2 - Can't find input file
  13.                      Output file exists and overwrite not specified
  14.                  3 - Input OPEN error
  15.                      Output OPEN error
  16.                      Output SEEK error
  17.                  9 - Input READ error
  18.                      Output WRITE error
  19.                      Input CLOSE error
  20.                      Output CLOSE error
  21. IPFC Notes:      In order to process the output from this program, you'll need the
  22.                  IPF Compiler (IPFC) which is part of the IBM Toolkit.  You will
  23.                  very likely see some warning messages when you compile the IPF
  24.                  file this program produces:
  25.  
  26.                  <TestFile.IPF:298> 306: Missing panel text in head level tag
  27.  
  28.                  This is (as near as I can figure) the result of having headings
  29.                  which are not followed by any text to be displayed.  The INF file
  30.                  seems to be fine and the message is just a warning, so I didn't
  31.                  worry much about it.
  32.  
  33. On the off-chance anyone cares: this program is public domain software.  Feel free to
  34. use it, abuse it, or post it - just don't charge money for it.  Look at the code, who
  35. would pay for this?
  36.  
  37. Given our litigious society...
  38.  
  39. DISCLAIMER
  40. Users of this program must accept this disclaimer of warranty:
  41.  
  42. "This program is supplied as is.  The original author disclaims all
  43. warranties, expressed or implied, including, without limitation,
  44. the warranties of merchantability and of fitness for any purpose.
  45. The original author assumes no liability for damages, direct or
  46. consequential, which may result from the use of this program."
  47.  
  48. */
  49.  
  50. Call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  51. Call SysLoadFuncs
  52.  
  53. myName = 'CIS2IPF'
  54. version = '1.03'
  55. destinationFile = ''
  56. switchAt = 0
  57. quietMode = 0
  58. overWriteOK = 0
  59. newMsg = 0
  60. okayToStart = 0
  61. count = 0
  62. breakLvl3Occurred = 0
  63. linesWritten = 0
  64.  
  65. /*
  66. These literals are used to determine if the current input line indicates
  67. a break, or heading, line.
  68. */
  69. breakLvl1 = '#: 0'
  70. breakLvl2 = '#: '
  71. breakLvl3 = 'Sb: '
  72. breakLvl4 = 'Fm: '
  73. announcementFlag = 'A'
  74.  
  75. /*
  76. The length of the break indicator literals is used repetitively in a loop.  I
  77. hoped to improve performance by only calculating it once.
  78. */
  79. lenBreakLvl1 = Length(breakLvl1)
  80. lenBreakLvl2 = Length(breakLvl2)
  81. lenBreakLvl3 = Length(breakLvl3)
  82. lenBreakLvl4 = Length(breakLvl4)
  83.  
  84. prevBreakLvl2Ind = 'XjUnKx'
  85. prevBreakLvl3Ind = 'XjUnKx'
  86.  
  87. Select
  88.   When Words(Arg(1)) = 0 Then
  89.     Do
  90.       Call ShowSyntax
  91.       Call EndThisPlease 1
  92.     End
  93.   When (Translate(Word(Arg(1), 1) = '/H')) |,
  94.        (Translate(Word(Arg(1), 1) = '/?')) |,
  95.        (Translate(Word(Arg(1), 1) = '-H')) |,
  96.        (Translate(Word(Arg(1), 1) = 'HELP')) |,
  97.        (Translate(Word(Arg(1), 1) = '?')) Then
  98.     Do
  99.       Call ShowSyntax
  100.       Call EndThisPlease 0
  101.     End
  102.   When Words(Arg(1)) > 0 Then NOP
  103.   Otherwise
  104.     Do
  105.       Call ShowSyntax
  106.       Call EndThisPlease 0
  107.     End
  108. End
  109.  
  110. /*
  111. Make sure the source file exists.
  112. */
  113. rc = CheckForFile( Word(Arg(1), 1) )
  114. If rc = 0 Then
  115.   sourceFile = fullPathName
  116. Else
  117.   Do
  118.     Say myName':' Word(Arg(1), 1) 'does not exist'
  119.     Call EndThisPlease 2
  120.   End
  121.  
  122. /*
  123. If the destination file isn't specified, create a destination file name
  124. from the source file.  If it is specified, make sure it doesn't already
  125. exist or that overwrite was specified.
  126. */
  127. If Words(Arg(1)) > 1 Then
  128.   Do
  129.     Call GetSwitches Arg(1)
  130.     If switchAt > 2 Then
  131.       Call CheckArgForDestination Arg(1)
  132.     Else
  133.       Call MakeDestinationFromSource
  134.   End
  135. Else
  136.   Call MakeDestinationFromSource
  137.  
  138. If quietMode Then
  139.   NOP
  140. Else
  141.   Do
  142.     Call SysCls
  143.     pos = SysCurPos(1,0)
  144.     Call ShowParms
  145.   End
  146.  
  147. /*
  148. Make a title for the IPF file from the source file name.
  149. */
  150. reversedSource = Reverse(sourceFile)
  151. Parse Var reversedSource . '.' reversedFileTitle '\' .
  152. fileTitle = Reverse(reversedFileTitle)
  153. Drop reversedSource reversedFileTitle
  154.  
  155. Call LoadSpecialSymbols
  156.  
  157. Call OpenFilesAndSuch
  158.  
  159. /*
  160. This is the main processing loop.
  161. */
  162. Do While Lines(sourceFile) > 0
  163.   Call ProcessTheSource
  164. End
  165.  
  166. Call CloseFilesAndSuch
  167.  
  168. Exit 0
  169.  
  170. GetSwitches:
  171.  
  172. i = 0
  173. Do Until i = Words(Arg(1))
  174.   i = i + 1
  175.   Select
  176.     When Translate(Word(Arg(1), i)) = '-W' Then
  177.       Do
  178.         overWriteOK = 1
  179.         If switchAt = 0 Then
  180.           switchAt = i
  181.         Else
  182.           If switchAt > i Then
  183.             switchAt = i
  184.           Else
  185.             NOP
  186.       End
  187.     When Translate(Word(Arg(1), i)) = '-Q' Then
  188.       Do
  189.         quietMode = 1
  190.         If switchAt = 0 Then
  191.           switchAt = i
  192.         Else
  193.           If switchAt > i Then
  194.             switchAt = i
  195.           Else
  196.             NOP
  197.       End
  198.     Otherwise NOP
  199.   End
  200. End
  201.  
  202. Return
  203.  
  204. MakeDestinationFromSource:
  205.  
  206. reversedArg = Reverse(fullPathName)
  207. Parse Var reversedArg . '.' reversedFileName
  208. destinationFile = Reverse(reversedFileName) || '.IPF'
  209. rc = CheckForFile( destinationFile )
  210. If (rc = 0 & overWriteOK) | rc = 1 Then
  211.   NOP
  212. Else
  213.   Do
  214.     Say myName':' destinationFile 'exists and overwrite was not specified'
  215.     Call EndThisPlease 2
  216.   End
  217.  
  218. Return
  219.  
  220. CheckArgForDestination:
  221.  
  222. rc = CheckForFile( Word(Arg(1), (switchAt - 1)) )
  223. Select
  224.   When rc = 0 & overWriteOK Then
  225.     destinationFile = fullPathName
  226.   When rc = 1 Then
  227.     destinationFile = Word(Arg(1), 2)
  228.   Otherwise
  229.     Do
  230.       Say myName':' Word(Arg(1), 2) 'exists and overwrite was not specified'
  231.       Call EndThisPlease 2
  232.     End
  233. End
  234.  
  235. Return
  236.  
  237. OpenFilesAndSuch:
  238.  
  239. rc = OpenFileForRead( sourceFile )
  240. If rc = 0 Then
  241.   NOP
  242. Else
  243.   Do
  244.     Say sourceFile 'OPEN READ failed'
  245.     Call EndThisPlease 3
  246.   End
  247.  
  248. rc = OpenFileForWrite( destinationFile )
  249. If rc = 0 Then
  250.   NOP
  251. Else
  252.   Do
  253.     Say sourceFile 'OPEN WRITE failed'
  254.     Call EndThisPlease 3
  255.   End
  256.  
  257. rc = PositionForWriteAtBeginning( destinationFile )
  258. If rc = 0 Then
  259.   NOP
  260. Else
  261.   Do
  262.     Say sourceFile 'SEEK failed'
  263.     Call EndThisPlease 3
  264.   End
  265.  
  266. Call WriteFile destinationFile, ':userdoc.'
  267. Call WriteFile destinationFile, ':title.'fileTitle
  268. Call WriteFile destinationFile, ':docprof toc=12345.'
  269.  
  270. If quietMode Then
  271.   NOP
  272. Else
  273.   Do
  274.     Parse Value SysCurPos() With row col
  275.     pos = SysCurPos(row, 2)
  276.     Say 'Record Count'
  277.   End
  278.  
  279. Return
  280.  
  281. ProcessTheSource:
  282.  
  283. Call ReadFile sourceFile
  284. count = count + 1
  285. If quietMode Then
  286.   NOP
  287. Else
  288.   Do
  289.     pos = SysCurPos(row, 15)
  290.     Say count
  291.   End
  292.  
  293. Select
  294.   When (Length(inputLine) > lenBreakLvl1) & ,
  295.        (Substr(inputLine, 1, lenBreakLvl1) = breakLvl1) Then
  296.     Do
  297.       Call BreakLevel1
  298.     End
  299.   When (Length(inputLine) > lenBreakLvl2) & ,
  300.        (Substr(inputLine, 1, lenBreakLvl2) = breakLvl2) Then
  301.     Do
  302.       If okayToStart Then Call BreakLevel2
  303.     End
  304.   When (Length(inputLine) > lenBreakLvl3) & ,
  305.        (Substr(inputLine, 1, lenBreakLvl3) = breakLvl3) Then
  306.     Do
  307.       If okayToStart Then Call BreakLevel3
  308.     End
  309.   When (Length(inputLine) > lenBreakLvl4) & ,
  310.        (Substr(inputLine, 1, lenBreakLvl4) = breakLvl4) Then
  311.     Do
  312.       If okayToStart Then Call BreakLevel4
  313.     End
  314.   Otherwise
  315.     Do
  316.       Call NormalText
  317.     End
  318. End
  319.  
  320. Return
  321.  
  322. BreakLevel1:
  323.  
  324. Call PutELinesTagIn
  325. newMsg = 1
  326. okayToStart = 1
  327. Call SubstituteSpecialSymbols inputLine
  328.  
  329. outputLine2 = ':h2. ' || modifiedString
  330. msgHeader.0 = 5
  331. Do k = 1 To msgHeader.0
  332.   msgHeader.k = ''
  333. End
  334.  
  335. Call SubstituteSpecialSymbols inputLine
  336. msgHeader.1 = modifiedString
  337. Call ReadFile sourceFile
  338. Call SubstituteSpecialSymbols inputLine
  339. msgHeader.2 = modifiedString
  340.  
  341. outputLine1 = ':h1. ' || modifiedString
  342. Call WriteFile destinationFile, outputLine1
  343. Call WriteFile destinationFile, outputLine2
  344. Drop outputLine2
  345.  
  346. breakLvlCount = 2
  347.  
  348. Return
  349.  
  350. BreakLevel2:
  351.  
  352. msgHeader.0 = 5
  353. Do k = 1 To msgHeader.0
  354.   msgHeader.k = ''
  355. End
  356.  
  357. newMsg = 1
  358. Call SubstituteSpecialSymbols inputLine
  359. msgHeader.1 = modifiedString
  360. Parse Var inputLine . ' ' . ' ' breakLvl2Ind
  361. If breakLvl2Ind \= prevBreakLvl2Ind Then
  362.   Do
  363.     Call PutELinesTagIn
  364.     aString = Substr(inputLine, lenBreakLvl2)
  365.     Parse Var aString . ' ' sectionHeader
  366.     Call SubstituteSpecialSymbols sectionHeader
  367.     breakLvlCount = breakLvlCount + 1
  368.     If breakLvlCount > 3 Then breakLvlCount = 3
  369.     outputLine1 = ':h' || breakLvlCount || '. ' || modifiedString
  370.     Call WriteFile destinationFile, outputLine1
  371.     prevBreakLvl2Ind = breakLvl2Ind
  372.   End
  373.  
  374. Call ReadFile sourceFile
  375. Call SubstituteSpecialSymbols inputLine
  376. msgHeader.2 = modifiedString
  377.  
  378. Return
  379.  
  380. /*
  381. There are a couple of different ways this break level can be
  382. indicated.  We have to try them all.
  383. */
  384. BreakLevel3:
  385.  
  386. newMsg = 1
  387. Call SubstituteSpecialSymbols inputLine
  388. msgHeader.3 = modifiedString
  389. breakLvl3Ind1 = ''
  390. breakLvl3Ind2 = ''
  391. If Pos(announcementFlag, inputLine) > 0 Then
  392.   breakLvl3Ind = announcementFlag
  393. Else
  394.   Do
  395.     Parse Var inputLine . (breakLvl3) . '-#' breakLvl3Ind
  396.     If breakLvl3Ind = '' Then
  397.       Parse Var inputLine . (breakLvl3) . '-' breakLvl3Ind
  398.     Else
  399.       NOP
  400.     If breakLvl3Ind = '' Then
  401.       Parse Var inputLine . (breakLvl3) . '#' breakLvl3Ind
  402.     Else
  403.       NOP
  404.     If breakLvl3Ind = '' Then
  405.       Parse Var inputLine . (breakLvl3) breakLvl3Ind
  406.     Else
  407.       NOP
  408.   End
  409.  
  410. If breakLvl3Ind \= prevBreakLvl3Ind Then
  411.     Do
  412.       Call PutELinesTagIn
  413.       breakLvlCount = breakLvlCount + 1
  414.       If breakLvlCount > 4 Then breakLvlCount = 4
  415.       outputLine1 = ':h' || breakLvlCount || '. ' || modifiedString
  416.       Call WriteFile destinationFile, outputLine1
  417.       prevBreakLvl3Ind = breakLvl3Ind
  418.     End
  419. Else
  420.   NOP
  421.  
  422. breakLvl3Occurred = 1
  423.  
  424. Return
  425.  
  426. BreakLevel4:
  427.  
  428. Call PutELinesTagIn
  429. newMsg = 1
  430. Call SubstituteSpecialSymbols inputLine
  431. msgHeader.4 = modifiedString
  432. breakLvlCount = breakLvlCount + 1
  433. If breakLvlCount > 5 Then breakLvlCount = 5
  434. outputLine1 = ':h' || breakLvlCount || '. ' || modifiedString
  435. Call WriteFile destinationFile, outputLine1
  436.  
  437. Return
  438.  
  439. NormalText:
  440.  
  441. If newMsg & breakLvl3Occurred Then
  442.   Do
  443.     Call WriteFile destinationFile, ':p.'
  444.     Call WriteFile destinationFile, ':lines.'
  445.     linesWritten = 1
  446.     Do i = 1 to msgHeader.0
  447.       If msgHeader.i = '' Then
  448.         NOP
  449.       Else
  450.         Call WriteFile destinationFile, msgHeader.i
  451.     End
  452.     newMsg = 0
  453.     breakLvl3Occurred = 0
  454.   End
  455. Else
  456.   NOP
  457. If okayToStart Then
  458.   Do
  459.     Call SubstituteSpecialSymbolsInBodyText inputLine, ampersandSubscript
  460.     inputLine = modifiedString
  461.     Call SubstituteSpecialSymbolsInBodyText inputLine, colonSubscript
  462.     inputLine = modifiedString
  463.     Call SubstitutePeriodsInBodyText inputLine, periodSubscript
  464.     Call WriteFile destinationFile, modifiedString
  465.   End
  466. Else
  467.   NOP
  468.  
  469. Return
  470.  
  471. PutELinesTagIn:
  472.  
  473. If linesWritten Then
  474.   Do
  475.     Call WriteFile destinationFile, ':elines.'
  476.     linesWritten = 0
  477.   End
  478. Else
  479.   NOP
  480.  
  481. Return
  482.  
  483. SubstituteSpecialSymbols: Procedure Expose modifiedString specialSymbol. ipfSymbol.
  484.  
  485. /*
  486. The logic here is ugly because both the ampersand and period are special
  487. characters and are also used to indicate special characters.  We have to
  488. check to make sure each is substituted properly, not replacing an existing
  489. special character's IPF symbol.
  490.  
  491. It was rather difficult to get this to work.  Hopefully, you won't have to
  492. modify it.
  493. */
  494.  
  495. modifiedString = Arg(1)
  496.  
  497. If Length(modifiedString) = 0 Then
  498.   Return
  499. Else
  500.   NOP
  501.  
  502. z = specialSymbol.0
  503. Do i = 1 To specialSymbol.0
  504.   j = 1
  505.   leaveMe = 0
  506.   k = 1
  507.   Do While ( Pos( specialSymbol.i, modifiedString, j ) > 0 ) &,
  508.            ( Length(modifiedString) > 0 )
  509.     j = Pos( specialSymbol.i, modifiedString, j )
  510.     If (specialSymbol.i = specialSymbol.z) &,
  511.        (Pos( specialSymbol.i, modifiedString, k) > 0) Then
  512.       Do While (Pos( specialSymbol.i, modifiedString, k) > 0)
  513.         itIsAnIPFSymbol = 0
  514.         k = Pos( specialSymbol.i, modifiedString, k)
  515.         Do x = 1 To ipfSymbol.0
  516.           If Length(modifiedString) >= (k + Length(ipfSymbol.x) - 1) Then
  517.             If Substr(modifiedString, k, Length(ipfSymbol.x)) = ipfSymbol.x Then
  518.               Do
  519.                 itIsAnIPFSymbol = 1
  520.                 Leave x
  521.               End
  522.             Else
  523.               NOP
  524.           Else
  525.             NOP
  526.         End
  527.         If itIsAnIPFSymbol Then
  528.           Do
  529.             k = k + Length(ipfSymbol.x) + 1
  530.             If k >= Length(modifiedString) Then leaveMe = 1
  531.           End
  532.         Else
  533.           Do
  534.             Select
  535.               When k = 1 Then
  536.                 Do
  537.                   string2 = Substr(modifiedString, k + 1)
  538.                   modifiedString = ipfSymbol.i || string2
  539.                 End
  540.               When k = Length(modifiedString) Then
  541.                 Do
  542.                   string1 = Substr(modifiedString, 1, k - 1)
  543.                   modifiedString = string1 || ipfSymbol.i
  544.                 End
  545.               Otherwise
  546.                 Do
  547.                   string1 = Substr(modifiedString, 1, k - 1)
  548.                   string2 = Substr(modifiedString, k + 1)
  549.                   modifiedString = string1 || ipfSymbol.i || string2
  550.                 End
  551.             End
  552.             k = k + Length(ipfSymbol.i)
  553.             If k >= Length(modifiedString) Then leaveMe = 1
  554.           End
  555.         j = k
  556.       End
  557.     Else
  558.       Do
  559.         Select
  560.           When j = 1 Then
  561.             Do
  562.               string2 = Substr(modifiedString, j + 1)
  563.               modifiedString = ipfSymbol.i || string2
  564.             End
  565.           When j = Length(modifiedString) Then
  566.             Do
  567.               string1 = Substr(modifiedString, 1, j - 1)
  568.               modifiedString = string1 || ipfSymbol.i
  569.             End
  570.           Otherwise
  571.             Do
  572.               string1 = Substr(modifiedString, 1, j - 1)
  573.               string2 = Substr(modifiedString, j + 1)
  574.               modifiedString = string1 || ipfSymbol.i || string2
  575.             End
  576.         End
  577.         j = j + Length(ipfSymbol.i)
  578.         If j >= Length(modifiedString) Then leaveMe = 1
  579.       End
  580.     If leaveMe Then Leave
  581.   End
  582. End
  583.  
  584. Return
  585.  
  586. /*
  587. We only need to substitute some of the special symbols into the body text.
  588. */
  589. SubstituteSpecialSymbolsInBodyText: Procedure Expose modifiedString specialSymbol. ipfSymbol.
  590.  
  591. modifiedString = Arg(1)
  592. subscript = Arg(2)
  593.  
  594. j = 1
  595. Do While ( Pos( specialSymbol.subscript, modifiedString, j ) > 0 ) &,
  596.          ( Length(modifiedString) > 0 )
  597.   j = Pos( specialSymbol.subscript, modifiedString, j )
  598.   string1 = Substr(modifiedString, 1, j - 1)
  599.   string2 = Substr(modifiedString, j + 1)
  600.   modifiedString = string1 || ipfSymbol.subscript || string2
  601.   j = j + Length(ipfSymbol.subscript)
  602. End
  603.  
  604. Return
  605.  
  606. /*
  607. And, of course, periods aren't allowed in column one of the body text.  IPFC
  608. thinks they're macros.  How stupid of me not to have known.
  609. */
  610. SubstitutePeriodsInBodyText: Procedure Expose modifiedString specialSymbol. ipfSymbol.
  611.  
  612. modifiedString = Arg(1)
  613. subscript = Arg(2)
  614.  
  615. If ( Pos( specialSymbol.subscript, modifiedString, 1 ) = 1 ) &,
  616.          ( Length(modifiedString) > 1 ) Then
  617.   Do
  618.     modifiedString = ipfSymbol.subscript || Substr(Arg(1), 2)
  619.   End
  620. Else
  621.   If Length(modifiedString) = 1 Then
  622.   Do
  623.     modifiedString = ipfSymbol.subscript
  624.   End
  625.  
  626. Return
  627.  
  628. LoadSpecialSymbols:
  629.  
  630. /*
  631. None of the following symbols are allowed in heading text.  Note that the period
  632. is first and the ampersand is last.  This is important to the logic which replaces
  633. these special characters.
  634. */
  635.  
  636. specialSymbol.0 = 123
  637. specialSymbol.1 = '.'    /*Period              */
  638. periodSubscript = 1      /*Not allowed in column 1 of window body text */
  639. specialSymbol.2 = 'á'    /*a acute             */
  640. specialSymbol.3 = 'â'    /*a circumflex        */
  641. specialSymbol.4 = 'ä'    /*a umlaut            */
  642. specialSymbol.5 = 'Ä'    /*A umlaut            */
  643. specialSymbol.6 = 'à'    /*a grave             */
  644. specialSymbol.7 = 'æ'    /*ae ligature         */
  645. specialSymbol.8 = 'Æ'    /*AE ligature         */
  646. specialSymbol.9 = 'A'    /*Alpha               */
  647. specialSymbol.10 = '^'    /*and                 */
  648. specialSymbol.11 = 'Å'    /*angstrom            */
  649. specialSymbol.12 = 'å'    /*a overcircle        */
  650. specialSymbol.13 = 'Å'    /*A overcircle        */
  651. specialSymbol.14 = "'"    /*Apostrophe          */
  652. specialSymbol.15 = '╣'    /*ASCII code 185      */
  653. specialSymbol.16 = '║'    /*ASCII code 186      */
  654. specialSymbol.17 = '╗'    /*ASCII code 187      */
  655. specialSymbol.18 = '╝'    /*ASCII code 188      */
  656. specialSymbol.19 = '╚'    /*ASCII code 200      */
  657. specialSymbol.20 = '╔'    /*ASCII code 201      */
  658. specialSymbol.21 = '╩'    /*ASCII code 202      */
  659. specialSymbol.22 = '╦'    /*ASCII code 203      */
  660. specialSymbol.23 = '╠'    /*ASCII code 204      */
  661. specialSymbol.24 = '═'    /*ASCII code 205      */
  662. specialSymbol.25 = '╬'    /*ASCII code 206      */
  663. specialSymbol.26 = '*'    /*Asterisk            */
  664. specialSymbol.27 = '@'    /*At sign             */
  665. specialSymbol.28 = '\'    /*Back slash          */
  666. specialSymbol.29 = 'ß'    /*Beta                */
  667. specialSymbol.30 = '┴'    /*box ascender        */
  668. specialSymbol.31 = '┼'    /*box cross           */
  669. specialSymbol.32 = '┬'    /*box descender       */
  670. specialSymbol.33 = '─'    /*box horizontal      */
  671. specialSymbol.34 = '└'    /*box lower-left      */
  672. specialSymbol.35 = '┘'    /*box lower-right     */
  673. specialSymbol.36 = '┤'    /*box right junction  */
  674. specialSymbol.37 = '┌'    /*box upper-left      */
  675. specialSymbol.38 = '┐'    /*box upper-right     */
  676. specialSymbol.39 = '│'    /*box vertical        */
  677. specialSymbol.40 = 'ç'    /*c cedilla           */
  678. specialSymbol.41 = 'Ç'    /*C cedilla           */
  679. specialSymbol.42 = '^'    /*Caret symbol        */
  680. specialSymbol.43 = '"'    /*Close double quote  */
  681. specialSymbol.44 = '»'    /*Close French double */
  682.                           /*quote               */
  683. specialSymbol.45 = "'"    /*Close single quote  */
  684. specialSymbol.46 = ','    /*Comma               */
  685. specialSymbol.47 = ':'    /*Colon               */
  686. colonSubscript = 47       /*Not allowed in window body text */
  687. specialSymbol.48 = '-'    /*Dash                */
  688. specialSymbol.49 = '°'    /*degree              */
  689. specialSymbol.50 = '÷'    /*divide              */
  690. specialSymbol.51 = '$'    /*Dollar sign         */
  691. specialSymbol.52 = '·'    /*dot                 */
  692. specialSymbol.53 = ''    /*Down arrow          */
  693. specialSymbol.54 = 'é'    /*e acute             */
  694. specialSymbol.55 = 'É'    /*E acute             */
  695. specialSymbol.56 = 'ê'    /*e circumflex        */
  696. specialSymbol.57 = 'ë'    /*e umlaut            */
  697. specialSymbol.58 = 'è'    /*e grave             */
  698. specialSymbol.59 = '-'    /*Em dash             */
  699. specialSymbol.60 = '-'    /*En dash             */
  700. specialSymbol.61 = '='    /*Equal sign          */
  701. specialSymbol.62 = '!'    /*Exclamation point   */
  702. specialSymbol.63 = 'ƒ'    /*function of         */
  703. specialSymbol.64 = '>'    /*Greater than        */
  704. specialSymbol.65 = ''    /*House               */
  705. specialSymbol.66 = '-'    /*Hyphen              */
  706. specialSymbol.67 = 'í'    /*i acute             */
  707. specialSymbol.68 = 'î'    /*i circumflex        */
  708. specialSymbol.69 = 'ï'    /*i umlaut            */
  709. specialSymbol.70 = 'ì'    /*i grave             */
  710. specialSymbol.71 = '¡'    /*inverted exclamation*/
  711.                           /*mark                */
  712. specialSymbol.72 = '¿'    /*inverted question   */
  713.                           /*mark                */
  714. specialSymbol.73 = ''    /*Left arrow          */
  715. specialSymbol.74 = '{'    /*Left brace          */
  716. specialSymbol.75 = '['    /*Left bracket        */
  717. specialSymbol.76 = '('    /*Left parenthesis    */
  718. specialSymbol.77 = '¬'    /*logical not         */
  719. specialSymbol.78 = '-'    /*M dash              */
  720. specialSymbol.79 = '-'    /*Minus sign          */
  721. specialSymbol.80 = 'µ'    /*Mu                  */
  722. specialSymbol.81 = '-'    /*N dash              */
  723. specialSymbol.82 = 'ñ'    /*n tidle             */
  724. specialSymbol.83 = 'Ñ'    /*N tidle             */
  725. specialSymbol.84 = '¬'    /*not symbol          */
  726. specialSymbol.85 = '#'    /*Number sign         */
  727. specialSymbol.86 = 'ó'    /*o acute             */
  728. specialSymbol.87 = 'ô'    /*o circumflex        */
  729. specialSymbol.88 = 'ò'    /*o grave             */
  730. specialSymbol.89 = 'ö'    /*o umlaut            */
  731. specialSymbol.90 = 'Ö'    /*O umlaut            */
  732. specialSymbol.91 = '¼'    /*one fourth          */
  733. specialSymbol.92 = '½'    /*one half            */
  734. specialSymbol.93 = '"'    /*Open double quote   */
  735. specialSymbol.94 = '«'    /*Open French double  */
  736.                           /*quote               */
  737. specialSymbol.95 = "`"    /*Open single quote   */
  738. specialSymbol.96 = '%'    /*Percent             */
  739. specialSymbol.97 = '+'    /*Plus sign           */
  740. specialSymbol.98 = '±'    /*plusminus           */
  741. specialSymbol.99 = '£'    /*pound sterling      */
  742. specialSymbol.100 = '}'    /*Right brace         */
  743. specialSymbol.101 = ']'    /*Right bracket       */
  744. specialSymbol.102 = ')'    /*Right parenthesis   */
  745. specialSymbol.103 = ';'    /*Semicolon           */
  746. specialSymbol.104 = '░'    /*shaded box 1/4 dots */
  747. specialSymbol.105 = '▒'    /*shaded box 1/2 dots */
  748. specialSymbol.106 = '▓'    /*shaded box 3/4 dots */
  749. specialSymbol.107 = '/'    /*Slash               */
  750. specialSymbol.108 = '█'    /*solid box           */
  751. specialSymbol.109 = '▄'    /*solid box bottom    */
  752.                           /*half                */
  753. specialSymbol.110 = '|'    /*Split vertical bar  */
  754.                           /*(piping symbol)     */
  755. specialSymbol.111 = '■'    /*square bullet       */
  756. specialSymbol.112 = '²'    /*superscript 2       */
  757. specialSymbol.113 = '~'    /*Tilde               */
  758. specialSymbol.114 = 'ú'    /*u acute             */
  759. specialSymbol.115 = 'û'    /*u circumflex        */
  760. specialSymbol.116 = 'ù'    /*u grave             */
  761. specialSymbol.117 = 'ü'    /*u umlaut            */
  762. specialSymbol.118 = 'Ü'    /*U umlaut            */
  763. specialSymbol.119 = '_'    /*Underscore          */
  764. specialSymbol.120 = 'ª'    /*underscored a       */
  765. specialSymbol.121 = 'º'    /*underscored o       */
  766. specialSymbol.122 = 'ÿ'    /*y umlaut            */
  767. specialSymbol.123 = '&'    /*Ampersand           */
  768. ampersandSubscript = 123   /*Not allowed in window body text */
  769.  
  770. /*
  771. The '&' is last because it is also used to indicate a special symbol.  Leave
  772. it as the last entry if more special symbols are added.
  773. */
  774.  
  775. ipfSymbol.0 = 123
  776. ipfSymbol.1 = '&per.'               /*Period               .    */
  777. ipfSymbol.2 = '&aa.'                /*a acute              á    */
  778. ipfSymbol.3 = '&ac.'                /*a circumflex         â    */
  779. ipfSymbol.4 = '&ae.'                /*a umlaut             ä    */
  780. ipfSymbol.5 = '&Ae.'                /*A umlaut             Ä    */
  781. ipfSymbol.6 = '&ag.'                /*a grave              à    */
  782. ipfSymbol.7 = 'æ.'             /*ae ligature          æ    */
  783. ipfSymbol.8 = 'Æ.'             /*AE ligature          Æ    */
  784. ipfSymbol.9 = '&Alpha.'             /*Alpha                A    */
  785. ipfSymbol.10 = '&and.'               /*and                  ^    */
  786. ipfSymbol.11 = '&angstrom.'          /*angstrom             Å    */
  787. ipfSymbol.12 = '&ao.'                /*a overcircle         å    */
  788. ipfSymbol.13 = '&Ao.'                /*A overcircle         Å    */
  789. ipfSymbol.14 = '&apos.'              /*Apostrophe           '    */
  790. ipfSymbol.15 = '&bx2022.'            /*ASCII code 185       ╣    */
  791. ipfSymbol.16 = '&bx2020.'            /*ASCII code 186       ║    */
  792. ipfSymbol.17 = '&bx0022.'            /*ASCII code 187       ╗    */
  793. ipfSymbol.18 = '&bx2002.'            /*ASCII code 188       ╝    */
  794. ipfSymbol.19 = '&bx2200.'            /*ASCII code 200       ╚    */
  795. ipfSymbol.20 = '&bx0220.'            /*ASCII code 201       ╔    */
  796. ipfSymbol.21 = '&bx2202.'            /*ASCII code 202       ╩    */
  797. ipfSymbol.22 = '&bx0222.'            /*ASCII code 203       ╦    */
  798. ipfSymbol.23 = '&bx2220.'            /*ASCII code 204       ╠    */
  799. ipfSymbol.24 = '&bx0202.'            /*ASCII code 205       ═    */
  800. ipfSymbol.25 = '&bx2222.'            /*ASCII code 206       ╬    */
  801. ipfSymbol.26 = '&asterisk.'          /*Asterisk             *    */
  802. ipfSymbol.27 = '&atsign.'            /*At sign              @    */
  803. ipfSymbol.28 = '&bslash.'            /*Back slash           \    */
  804. ipfSymbol.29 = '&Beta.'              /*Beta                 ß    */
  805. ipfSymbol.30 = '&bxas.'              /*box ascender         ┴    */
  806. ipfSymbol.31 = '&bxcr.'              /*box cross            ┼    */
  807. ipfSymbol.32 = '&bxde.'              /*box descender        ┬    */
  808. ipfSymbol.33 = '&bxh.'               /*box horizontal       ─    */
  809. ipfSymbol.34 = '&bxll.'              /*box lower-left       └    */
  810. ipfSymbol.35 = '&bxlr.'              /*box lower-right      ┘    */
  811. ipfSymbol.36 = '&bxri.'              /*box right junction   ┤    */
  812. ipfSymbol.37 = '&bxul.'              /*box upper-left       ┌    */
  813. ipfSymbol.38 = '&bxur.'              /*box upper-right      ┐    */
  814. ipfSymbol.39 = '&bxv.'               /*box vertical         │    */
  815. ipfSymbol.40 = '&cc.'                /*c cedilla            ç    */
  816. ipfSymbol.41 = '&Cc.'                /*C cedilla            Ç    */
  817. ipfSymbol.42 = '&caret.'             /*Caret symbol         ^    */
  818. ipfSymbol.43 = '&cdq.'               /*Close double quote   "    */
  819. ipfSymbol.44 = '&cdqf.'              /*Close French double  »    */
  820.                                      /*quote                     */
  821. ipfSymbol.45 = '&csq.'               /*Close single quote   '    */
  822. ipfSymbol.46 = '&comma.'             /*Comma                ,    */
  823. ipfSymbol.47 = '&colon.'             /*Colon                :    */
  824. ipfSymbol.48 = '&dash.'              /*Dash                 -    */
  825. ipfSymbol.49 = '°ree.'            /*degree               °    */
  826. ipfSymbol.50 = '÷.'            /*divide               ÷    */
  827. ipfSymbol.51 = '&dollar.'            /*Dollar sign          $    */
  828. ipfSymbol.52 = '&dot.'               /*dot                  ·    */
  829. ipfSymbol.53 = '&darrow.'            /*Down arrow               */
  830. ipfSymbol.54 = '&ea.'                /*e acute              é    */
  831. ipfSymbol.55 = '&Ea.'                /*E acute              É    */
  832. ipfSymbol.56 = '&ec.'                /*e circumflex         ê    */
  833. ipfSymbol.57 = '&ee.'                /*e umlaut             ë    */
  834. ipfSymbol.58 = '&eg.'                /*e grave              è    */
  835. ipfSymbol.59 = '&emdash.'            /*Em dash              -    */
  836. ipfSymbol.60 = '&endash.'            /*En dash              -    */
  837. ipfSymbol.61 = '&eq.'                /*Equal sign           =    */
  838. ipfSymbol.62 = '&xclm.'              /*Exclamation point    !    */
  839. ipfSymbol.63 = '&fnof.'              /*function of          ƒ    */
  840. ipfSymbol.64 = '>sym.'             /*Greater than         >    */
  841. ipfSymbol.65 = '&house.'             /*House                    */
  842. ipfSymbol.66 = '&hyphen.'            /*Hyphen               -    */
  843. ipfSymbol.67 = '&ia.'                /*i acute              í    */
  844. ipfSymbol.68 = '&ic.'                /*i circumflex         î    */
  845. ipfSymbol.69 = '&ie.'                /*i umlaut             ï    */
  846. ipfSymbol.70 = '&ig.'                /*i grave              ì    */
  847. ipfSymbol.71 = '&inve.'              /*inverted exclamation ¡    */
  848.                                      /*mark                      */
  849. ipfSymbol.72 = '&invq.'              /*inverted question    ¿    */
  850.                                      /*mark                      */
  851. ipfSymbol.73 = '&larrow.'            /*Left arrow               */
  852. ipfSymbol.74 = '&lbrace.'            /*Left brace           {    */
  853. ipfSymbol.75 = '&lbracket.'          /*Left bracket         [    */
  854. ipfSymbol.76 = '&lpar.'              /*Left parenthesis     (    */
  855. ipfSymbol.77 = '&lnot.'              /*logical not          ¬    */
  856. ipfSymbol.78 = '&mdash.'             /*M dash               -    */
  857. ipfSymbol.79 = '&minus.'             /*Minus sign           -    */
  858. ipfSymbol.80 = '&mu.'                /*Mu                   µ    */
  859. ipfSymbol.81 = '&ndash.'             /*N dash               -    */
  860. ipfSymbol.82 = '&nt.'                /*n tidle              ñ    */
  861. ipfSymbol.83 = '&Nt.'                /*N tidle              Ñ    */
  862. ipfSymbol.84 = '&lnot.'              /*not symbol           ¬    */
  863. ipfSymbol.85 = '&numsign.'           /*Number sign          #    */
  864. ipfSymbol.86 = '&oa.'                /*o acute              ó    */
  865. ipfSymbol.87 = '&oc.'                /*o circumflex         ô    */
  866. ipfSymbol.88 = '&og.'                /*o grave              ò    */
  867. ipfSymbol.89 = '&oe.'                /*o umlaut             ö    */
  868. ipfSymbol.90 = '&Oe.'                /*O umlaut             Ö    */
  869. ipfSymbol.91 = '¼.'            /*one fourth           ¼    */
  870. ipfSymbol.92 = '½.'            /*one half             ½    */
  871. ipfSymbol.93 = '&odq.'               /*Open double quote    "    */
  872. ipfSymbol.94 = '&odqf.'              /*Open French double   «    */
  873.                                      /*quote                     */
  874. ipfSymbol.95 = '&osq.'               /*Open single quote    `    */
  875. ipfSymbol.96 = '&percent.'           /*Percent              %    */
  876. ipfSymbol.97 = '&plus.'              /*Plus sign            +    */
  877. ipfSymbol.98 = '&plusmin.'           /*plusminus            ±    */
  878. ipfSymbol.99 = '&Lsterling.'         /*pound sterling       £    */
  879. ipfSymbol.100 = '&rbrace.'            /*Right brace          }    */
  880. ipfSymbol.101 = '&rbracket.'          /*Right bracket        ]    */
  881. ipfSymbol.102 = '&rpar.'              /*Right parenthesis    )    */
  882. ipfSymbol.103 = '&semi.'              /*Semicolon            ;    */
  883. ipfSymbol.104 = '&box14.'             /*shaded box 1/4 dots  ░    */
  884. ipfSymbol.105 = '&box12.'             /*shaded box 1/2 dots  ▒    */
  885. ipfSymbol.106 = '&box34.'             /*shaded box 3/4 dots  ▓    */
  886. ipfSymbol.107 = '&slash.'             /*Slash                /    */
  887. ipfSymbol.108 = '&BOX.'               /*solid box            █    */
  888. ipfSymbol.109 = '&BOXBOT.'            /*solid box bottom     ▄    */
  889.                                       /*half                      */
  890. ipfSymbol.110 = '&splitvbar.'         /*Split vertical bar   |    */
  891.                                       /*(piping symbol)           */
  892. ipfSymbol.111 = '&sqbul.'             /*square bullet        ■    */
  893. ipfSymbol.112 = '².'              /*superscript 2        ²    */
  894. ipfSymbol.113 = '&tilde.'             /*Tilde                ~    */
  895. ipfSymbol.114 = '&ua.'                /*u acute              ú    */
  896. ipfSymbol.115 = '&uc.'                /*u circumflex         û    */
  897. ipfSymbol.116 = '&ug.'                /*u grave              ù    */
  898. ipfSymbol.117 = '&ue.'                /*u umlaut             ü    */
  899. ipfSymbol.118 = '&Ue.'                /*U umlaut             Ü    */
  900. ipfSymbol.119 = '&us.'                /*Underscore           _    */
  901. ipfSymbol.120 = '&aus.'               /*underscored a        ª    */
  902. ipfSymbol.121 = '&ous.'               /*underscored o        º    */
  903. ipfSymbol.122 = '&ye.'                /*y umlaut             ÿ    */
  904. ipfSymbol.123 = '&.'               /*Ampersand            &    */
  905.  
  906. Return
  907.  
  908. CloseFilesAndSuch:
  909.  
  910. Call PutELinesTagIn
  911. Call WriteFile destinationFile, ':euserdoc.'
  912.  
  913. rc = CloseFile( destinationFile )
  914.  
  915. If rc = 0 Then
  916.   NOP
  917. Else
  918.   Say myName '* File close error for' destinationFile
  919.  
  920. prevRC = rc
  921. rc = CloseFile( sourceFile )
  922.  
  923. If rc = 0 Then
  924.   NOP
  925. Else
  926.   Say myName '* File close error for' sourceFile
  927.  
  928. If (rc \= 0) | (prevRC \= 0) Then
  929.   Call EndThisPlease 9
  930. Else
  931.   NOP
  932.  
  933. Return
  934.  
  935. /*
  936. Make sure the input file exists, and return its full path name
  937. */
  938. CheckForFile: Procedure Expose fullPathName
  939.  
  940. fullPathName = Stream(Arg(1), 'C', 'QUERY EXISTS')
  941. If fullPathName = '' Then
  942.   rc = 1
  943. Else
  944.   rc = 0
  945.  
  946. Return rc
  947.  
  948. /*
  949. Open the file specified in the parameter for read only.
  950. */
  951. OpenFileForRead: Procedure Expose quietMode
  952.  
  953. aString = Stream(Arg(1), 'C', 'OPEN READ')
  954.  
  955. If quietMode Then
  956.   NOP
  957. Else
  958.   Say ' ' Arg(1) 'OPEN READ status is' aString
  959.  
  960. If aString = 'READY:' Then
  961.   rc = 0
  962. Else
  963.   rc = 1
  964.  
  965. Return rc
  966.  
  967. /*
  968. Read the file specified in the parameter.
  969. */
  970. ReadFile:
  971.  
  972. Call ON NOTREADY NAME ReadFileErr
  973.  
  974. inputLine = Linein(Arg(1))
  975.  
  976. CALL OFF NOTREADY
  977.  
  978. Return
  979.  
  980. /*
  981. Oops, an error occurred on read.
  982. */
  983. ReadFileErr:
  984.  
  985. Say myName '* File Read Error!'
  986.  
  987. Call EndThisPlease 9
  988.  
  989. Return
  990.  
  991. /*
  992. Open the file specified in the parameter for output.
  993. */
  994. OpenFileForWrite: Procedure Expose quietMode
  995.  
  996. aString = Stream(Arg(1), 'C', 'OPEN WRITE')
  997.  
  998. If quietMode Then
  999.   NOP
  1000. Else
  1001.   Say ' ' Arg(1) 'OPEN WRITE status is' aString
  1002.  
  1003. If aString = 'READY:' Then
  1004.   rc = 0
  1005. Else
  1006.   rc = 1
  1007.  
  1008. Return rc
  1009.  
  1010. /*
  1011. Output a record to the file.
  1012. */
  1013. WriteFile:
  1014.  
  1015. CALL ON NOTREADY NAME WriteFileErr
  1016.  
  1017. Call Lineout Arg(1), Arg(2)
  1018.  
  1019. CALL OFF NOTREADY
  1020.  
  1021. Return
  1022.  
  1023. /*
  1024. Oops, an error occurred on output.
  1025. */
  1026. WriteFileErr:
  1027.  
  1028. Say myName '* File Write Error!'
  1029.  
  1030. Call EndThisPlease 9
  1031.  
  1032. Return
  1033.  
  1034. /*
  1035. The REXX default is to append to a file.  We don't want to do that, so
  1036. this subroutine positions the write pointer at the beginning of
  1037. the file specified in the parameter.
  1038. */
  1039. PositionForWriteAtBeginning: Procedure Expose quietMode
  1040.  
  1041. aString = Stream(Arg(1), 'C', 'SEEK =1')
  1042.  
  1043. aString = Stream(Arg(1), 'S')
  1044.  
  1045. If quietMode Then
  1046.   NOP
  1047. Else
  1048.   Say ' ' Arg(1) 'SEEK status is' aString
  1049.  
  1050. If aString = 'READY' Then
  1051.   rc = 0
  1052. Else
  1053.   rc = 1
  1054.  
  1055. Return rc
  1056.  
  1057. /*
  1058. Close the file specified in the parameter.
  1059. */
  1060. CloseFile: Procedure Expose quietMode
  1061.  
  1062. aString = Stream(Arg(1), 'C', 'CLOSE')
  1063.  
  1064. If quietMode Then
  1065.   NOP
  1066. Else
  1067.   Say ' ' Arg(1) 'CLOSE status is' aString
  1068.  
  1069. If aString = 'READY:' Then
  1070.   rc = 0
  1071. Else
  1072.   rc = 1
  1073.  
  1074. Return rc
  1075.  
  1076. ShowSyntax:
  1077.  
  1078. Say myName version 'Syntax:'
  1079. Say Copies(' ', Length(myName)) myName 'source-file [destination-file] [-W] [-Q]'
  1080. Say myName 'Creates an IPF file from your text file of CompuServe'
  1081. Say Copies(' ', Length(myName)) 'messages.  The default destination-file is the source-file with'
  1082. Say Copies(' ', Length(myName)) 'the extension IPF.'
  1083. Say myName 'switches: (separate them with spaces please)'
  1084. Say Copies(' ', Length(myName)) '-W   write over destination file if it exists'
  1085. Say Copies(' ', Length(myName)) '-Q   quiet mode (suppress messages)'
  1086.  
  1087. Return
  1088.  
  1089. /*
  1090. Show the parameters being used in this run.
  1091. */
  1092. ShowParms:
  1093.  
  1094. Say myName version ' ' Date() Time()
  1095. Say '  Source File:      ' sourceFile
  1096. Say '  Destination File: ' destinationFile
  1097. If overWriteOK Then
  1098.   Say '  Overwrite:         Yes' 
  1099. Else
  1100.   Say '  Overwrite:         No' 
  1101.  
  1102. Return
  1103.  
  1104. /*
  1105. Just what it says...
  1106. */
  1107. EndThisPlease:
  1108.  
  1109. If quietMode Then
  1110.   NOP
  1111. Else
  1112.   Say myName': return code =' Arg(1)
  1113.  
  1114. Exit Arg(1)
  1115.