home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 18 REXX / 18-REXX.zip / cmdpk164.zip / xhelp.cmd < prev    next >
OS/2 REXX Batch file  |  1998-01-10  |  22KB  |  636 lines

  1. /* This is CommandPak's xhelp command.                  */
  2. /* (w) 1997-98 Ulrich Möller                            */
  3. '@echo off'
  4.  
  5. signal on halt
  6.  
  7. nl = '0d0a'x           /* this is CR+LF (hex), helpful for defining help strings */
  8. extLevel = 0
  9.  
  10. helpList. = ''
  11. helpList.ALIAS = 'call msg getExtMsg("aliasHelp")'
  12. helpList.CD = 'call msg getExtMsg("cdHelp"), "cd"'
  13. helpList.CMDSHL = 'call msg getExtMsg("cmdshlHelp")'
  14. helpList.COPY = 'call msg getExtMsg("copyHelp"), "copy"'
  15. helpList.CP = 'call msg getExtMsg("copyHelp"), "cp"'
  16. helpList.DEF = 'call msg getExtMsg("defineHelp"), "def"'
  17. helpList.DEFINE = 'call msg getExtMsg("defineHelp"), "define"'
  18. helpList.DEL = 'call msg getExtMsg("delHelp"), "del"'
  19. helpList.DIR = 'call msg getExtMsg("dirHelp"), "dir"'
  20. helpList.EXIT = 'call msg getExtMsg("exitHelp")'
  21. helpList.HELP = 'call msg getExtMsg("helpHelp"), "help"'
  22. helpList.FL = 'call startView help.ref filelist'
  23. helpList.FOR = 'call msg getExtMsg("forHelp")'
  24. helpList.KEYS = 'call msg getExtMsg("keysHelp")'
  25. helpList.LN = 'call msg getExtMsg("lnHelp")'
  26. helpList.LS = 'call msg getExtMsg("dirHelp"), "ls"'
  27. helpList.LESS = 'call startView help.ref less'
  28. helpList.MV = 'call msg getExtMsg("renHelp"), "mv"'
  29. helpList.OPEN = 'call msg getExtMsg("openHelp")'
  30. helpList.PUSHD = 'call msg getExtMsg("pushdHelp")'
  31. helpList.POPD = 'call msg getExtMsg("pushdHelp")'
  32. helpList.QUERY = 'call msg getExtMsg("queryHelp")'
  33. helpList.QUIT = 'call msg getExtMsg("quitHelp")'
  34. helpList.REC = 'call msg getExtMsg("recurseHelp")'
  35. helpList.RECURSE = 'call msg getExtMsg("recurseHelp")'
  36. helpList.REN = 'call msg getExtMsg("renHelp"), "ren"'
  37. helpList.RULE = 'call msg getExtMsg("ruleHelp")'
  38. helpList.RX = 'call msg getExtMsg("rxHelp")'
  39. helpList.SDIR = 'call startView help.ref sdir'
  40. helpList.VER = 'call msg getExtMsg("versionMsg")'
  41. helpList.WATCHDRV = 'call msg getExtMsg("watchdrvHelp")'
  42. helpList.XCP = 'call msg getExtMsg("copyHelp"), "xcp"'
  43. helpList.XDEL = 'call msg getExtMsg("delHelp"), "xdel"'
  44. helpList.XDIR = 'call msg getExtMsg("dirHelp"), "xdir"'
  45. helpList.XHELP = 'call msg getExtMsg("helpHelp"), "xhelp"'
  46. helpList.XREN = 'call msg getExtMsg("renHelp"), "xren"'
  47. helpList._XRENEXPL = 'call msg getExtMsg("renExpl")'
  48.  
  49. escapeList.437 = 'auml=ä euml=ë iuml=ï ouml=ö uuml=ü Auml=Ä Ouml=Ö Uuml=Ü',
  50.     'aacute=á eacute=é iacute=í oacute=ó uacute=ú Eacute=É',
  51.     'agrave=à egrave=è egrave=ì ograve=ò ugrave=ù',
  52.     'acirc=â ecirc=ê icirc=î ocirc=ô ucirc=û',
  53.     'aring=å Aring=Å ntilde=ñ Ntilde=Ñ iexcl=¡ ccedil=ç Ccedil=Ç szlig=ß ',
  54.     'sect= frac14=¼ frac12=½ sup2=² sub3=ⁿ aelig=æ AElig=Æ pound=£ cent=¢ para= micro=µ lt=< gt=> amp=& quot=" nbsp= ',
  55.     'curren= plusmn=± laquo=« raquo=» uarrw= darrw= larrw= rarrw=',
  56.     /* now the codepage-specific ones */,
  57.     'Euml=E Iuml=I Aacute=A Iacute=I Oacute=O Uacute=U Agrave=A Egrave=E Igrave=I Ograve=O Ugrave=U',
  58.     'Ecirc=E Icirc=I Acirc=A Ocirc=O Ucirc=U yen=¥'
  59.  
  60. escapeList.850 = 'auml=ä euml=ë iuml=ï ouml=ö uuml=ü Auml=Ä Ouml=Ö Uuml=Ü',
  61.     'aacute=á eacute=é iacute=í oacute=ó uacute=ú Eacute=É',
  62.     'agrave=à egrave=è egrave=ì ograve=ò ugrave=ù',
  63.     'acirc=â ecirc=ê icirc=î ocirc=ô ucirc=û',
  64.     'aring=å Aring=Å ntilde=ñ Ntilde=Ñ iexcl=¡ ccedil=ç Ccedil=Ç szlig=ß ',
  65.     'sect= frac14=¼ frac12=½ sup2=² sub3=ⁿ aelig=æ AElig=Æ pound=£ cent=¢ para= micro=µ lt=< gt=> amp=& quot=" nbsp= ',
  66.     'curren= plusmn=± laquo=« raquo=» uarrw= darrw= larrw= rarrw=',
  67.     /* now the codepage-specific ones */,
  68.     'Euml=╙ Iuml=╫ Aacute=╡ Iacute=╓ Oacute=α Uacute=Θ Agrave=╖ Egrave=╘ Igrave=▐ Ograve=π Ugrave=δ',
  69.     'Ecirc=╥ Icirc=╫ Acirc=╢ Ocirc=Γ Ucirc=Ω yen=Y'
  70.  
  71. sysMsgList = 'SYS REX' /* list of prefixes to system messages */
  72.  
  73. call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
  74. call SysLoadFuncs
  75.  
  76. /* first detect colors out of environment vars */
  77. ansiReset = ""
  78.  
  79. /* coloring for <A HREF=""> */
  80. val = value('HELP.ANCHOR',,'OS2ENVIRONMENT')
  81. if (val \= "") then do
  82.     ansiAnchorOn = ansiValue(val)
  83.     ansiReset = '1b'x||'[0m'
  84. end
  85. else
  86.     ansiAnchorOn = ""
  87.  
  88. /* coloring for <B> */
  89. val = value('HELP.BOLD',,'OS2ENVIRONMENT')
  90. if (val \= "") then do
  91.     ansiBoldOn = ansiValue(val)
  92.     ansiReset = '1b'x||'[0m'
  93. end
  94. else
  95.     ansiBoldOn = ""
  96.  
  97. /* coloring for <I> */
  98. val = value('HELP.ITALICS',,'OS2ENVIRONMENT')
  99. if (val \= "") then do
  100.     ansiItalicsOn = ansiValue(val)
  101.     ansiReset = '1b'x||'[0m'
  102. end
  103. else
  104.     ansiItalicsOn = ""
  105.  
  106. /* default color for <I> */
  107. val = value('HELP.COLOR',,'OS2ENVIRONMENT')
  108. if (val \= "") then
  109.     ansiReset = '1b'x||'[0m'ansiValue(val)
  110.  
  111. imageString = ansiItalicsOn''
  112.  
  113. /* now process args */
  114.  
  115. parse arg args
  116.  
  117. _upper = 'helpList.'||translate(word(args, 1))
  118.  
  119. parse var args opt parameters
  120.  
  121. select
  122.   when (opt = '-c') then
  123.     call msg getExtMsg("cmdshlHelp")
  124.   when (opt = "") then
  125.     call msg getExtMsg("helpHelpFirst")
  126.   when (opt = '?') | (opt = '/?') | (opt = '-h') then
  127.     call msg getExtMsg("helpHelp"), "help"
  128.   when (opt = '-x') | (opt = '-X') then
  129.     call msg getExtMsg("helpHelpExampl"), "help"
  130.   when (opt = '-w') then
  131.     call msg getExtMsg("welcomeMsg")
  132.   when (opt = '-f') then
  133.     call msg getExtMsg(word(parameters, 1)), word(parameters, 2)
  134.   when (opt = '-F') then
  135.     call msg extractMsg(word(parameters, 1), word(parameters, 2)), word(parameters, 3)
  136.   /* output text directly */
  137.   when left(args, 1) = '"' then do
  138.     p2 = lastpos('"', args)
  139.     if p2 > 2 then
  140.         args = substr(args, 2, p2-2)
  141.         else do; call charout , SysGetMessage(1003); exit; end
  142.     call msg args
  143.   end
  144.   /* HELP LIST*/
  145.   when (translate(args) = "LIST") then do
  146.     str = getExtMsg("helpList")
  147.     /* now collect INF files on the bookshelf */
  148.     shelf = value('BOOKSHELF',, 'OS2ENVIRONMENT')
  149.     j = 0
  150.     do while (shelf \= "")
  151.         parse var shelf shelf2 ";" shelf
  152.         rc = SysFileTree(shelf2"\*.inf", found)
  153.         do i = 0 to found.0
  154.             parse var found.i fdate ftime fsize fattr fpath
  155.             if (fpath \= "") then do
  156.                 fname = lowercase(filespec('NAME', fpath))
  157.                 fname = left(fname, pos(".inf", fname)-1)
  158.                 j = j+1
  159.                 fname.j = fname
  160.             end
  161.         end
  162.     end
  163.  
  164.     /* now check all environment variables */
  165.     localqueue = rxqueue('create')
  166.     oldqueue = rxqueue('set', localqueue)
  167.     'set 2>&1 | rxqueue' localqueue
  168.     do while (queued() > 0)
  169.        parse pull line
  170.        say line
  171.     end /* do */
  172.     call rxqueue 'delete', localqueue
  173.     call rxqueue 'set', oldqueue
  174.  
  175.     /* now prepare output */
  176.     fname.0 = j
  177.     call sort
  178.     do i = 1 to j
  179.         str = str||fname.i" "
  180.     end
  181.     str = str||nl
  182.     call msg str
  183.   end /* when (LIST) */
  184.   when (left(args, 1) = "-") then
  185.     call msg strReplace(getExtMsg("invalidOptionMsg"), '%a', args), "xhelp"
  186.   /* known command, e.g. help dir */
  187.   when (symbol(_upper) = "VAR") then do
  188.     if (value(_upper) \= '') then
  189.         interpret value(_upper)
  190.     else cont = 1
  191.   end /* when */
  192.   otherwise
  193.     cont = 1
  194. end /* select */
  195.  
  196. if (cont=1) then do /* only one argument given */
  197.     /* help cmdref dir */
  198.     if (words(args) = 2) then do
  199.         book = value('HELP.'word(args, 1),,'OS2ENVIRONMENT')
  200.         if (book = "") then book = value(word(args, 1),,'OS2ENVIRONMENT')
  201.         if (pos("+", book) = 0) then book=""
  202.         if (book = "") then book = word(args, 1)
  203.         topic_ = word(args, 2)
  204.         call msg strReplace(strReplace(getExtMsg("bookshelfMsg"), '%a', book), '%b', topic_)
  205.         call startView book topic_
  206.                 /* search given book (arg 1) for given topic (arg 2) */
  207.     end
  208.     else do
  209.       sysmsg = 0
  210.       if (datatype(args) = "NUM") then
  211.           sysmsg = 1
  212.       else
  213.           do while (sysmsgList \= "")
  214.               parse var sysmsgList s_ sysmsgList
  215.               if ( (left(translate(args), length(s_)) = s_) & (datatype(substr(args, length(s_)+1))="NUM"))then /* numeric --> help for system message */
  216.                   sysmsg = 1
  217.           end
  218.       if (sysmsg) then
  219.         "call helpmsg" args    /* "helpmsg" should be in the OS/2 directory; try "helpmsg 2166" */
  220.       else do  /* non-numeric --> more checks nevessary */
  221.           if (pos('+', args) > 0) then do
  222.                                         /* there's a "+" sign --> display several INFs */
  223.             call msg strReplace(getExtMsg("callViewMsg"), '%a', args)
  224.             call startView args
  225.           end
  226.           else do
  227.             book = value('HELP.'args,,'OS2ENVIRONMENT')
  228.             if (book = "") then book = value(args,,'OS2ENVIRONMENT')
  229.             if (pos("+", book) = 0) then book=""
  230.             if (book \= "") then do
  231.                                         /* envir'variable  --> display several INFs */
  232.                 call msg strReplace(getExtMsg("callViewMsg"), '%a', book)
  233.                 call startView book
  234.             end
  235.             else if (stream(args, "c", "query exists") \= "") & (right(args, 4) \= ".inf") then
  236.                 call processExternalFile(args)
  237.             else do
  238.                 loc = SysSearchPath("BOOKSHELF", args)
  239.                 if (loc = "") then loc = SysSearchPath("BOOKSHELF", args||".inf")
  240.                 if (loc \= "") then do     /* argument is an existing INF file --> open it */
  241.                   call msg strReplace(getExtMsg("callViewMsg"), '%a', loc)
  242.                   call startView loc
  243.                 end
  244.                 else do /* otherwise search whole bookshelf for args */
  245.                   topic_ = args
  246.                   call msg strReplace(strReplace(getExtMsg("bookshelfMsg"), '%a', "BOOKSHELF"), '%b', topic_)
  247.                   call startView '/'||topic_  /* cool feature: "view /<topic>" will search bookshelf for <topic>! */
  248.                 end
  249.             end
  250.           end
  251.      end
  252.     end
  253. end /* if */
  254.  
  255. exit
  256.  
  257. halt:
  258.     say ansiReset
  259.     call msg getExtMsg("abortMsg"), "xhelp"
  260. exit
  261.  
  262. strReplace: procedure
  263.     /* syntax: result = strReplace(str, old, new) */
  264.     /* will replace a by b in oldstr */
  265.     parse arg str, old, new
  266.     p = pos(old, str)
  267.     if (p > 0) then
  268.         str = left(str, p-1)||new||substr(str,p+length(old))
  269.     drop p
  270. return str
  271.  
  272. lowercase: procedure
  273.     return translate(arg(1), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
  274.  
  275. startView: procedure
  276.     parse arg args
  277.     if (sysSearchPath('PATH', 'VIEW.EXE') \= "") then
  278.         'start view' args
  279.     else call msg getExtMsg("noViewMsg")
  280. return
  281.  
  282. sort:  procedure expose fname.
  283.    M = 1
  284.    do while (9 * M + 4) < fname.0
  285.       M = M * 3 + 1
  286.    end /* do while */
  287.                         /* sort fname                                  */
  288.    do while M > 0
  289.       K = fname.0 - M
  290.       do J = 1 to K
  291.          Q = J
  292.          do while Q > 0
  293.             L = Q + M
  294.             if translate(fname.Q) <<= translate(fname.L) then
  295.               leave
  296.                         /* switch elements                            */
  297.             tmp      = fname.Q
  298.             fname.Q = fname.L
  299.             fname.L = tmp
  300.             Q = Q - M
  301.          end /* do while Q > 0 */
  302.       end /* do J = 1 to K */
  303.       M = M % 3
  304.    end /* while M > 0 */
  305. return
  306.  
  307. sayBreak:
  308.     call charout , ansiReset
  309.     if (arg(1) = "") then do
  310.         call charout , '0d0a'x||copies(" ",indent.level_)
  311.         xpos = indent.level_
  312.     end
  313.     else do
  314.         call charout , '0d0a'x||copies(" ",arg(1))
  315.         xpos = arg(1)
  316.     end
  317.     call setColors
  318.     lastChar = " "
  319. return
  320.  
  321. sayChar: procedure expose lastChar xpos
  322.     call charout , arg(1)
  323.     lastChar = arg(1)
  324.     xpos = xpos+length(arg(1))
  325. return
  326.  
  327. setColors:
  328.     call charout , ansiReset
  329.     if (anchor) then
  330.         call charout , ansiAnchorOn
  331.     if (bold) then
  332.         call charout , ansiBoldOn
  333.     if (italics) then
  334.         call charout , ansiItalicsOn
  335. return
  336.  
  337. HTMLerror:
  338.     l_ = sigl
  339.     say "HTML error in line" l_":"
  340.     say sourceline(l_)
  341.     exit
  342.  
  343. oldRexxUtils:
  344.     codepage=437
  345. signal weiter
  346.  
  347. sayHTML: /* Syntax: sayHTML <htmlstr>)*/
  348.     signal on novalue name HTMLerror
  349.  
  350.     signal on syntax name oldRexxUtils
  351.     codepage = SysQueryProcessCodePage()
  352.     weiter:
  353.     signal off failure
  354.  
  355.     call charout , getExtMsg("formattingMsg")"..."
  356.     txt = arg(1)||" "||'00'x
  357.         /* a little cheat for making word break in the last line work*/
  358.     do while (pos('0d0a'x, txt) > 0)
  359.         txt = strReplace(txt, '0d0a'x, '00'x)
  360.     end
  361.     call charout , "."
  362.     do while (pos('0d'x, txt) > 0)
  363.         txt = strReplace(txt, '0d'x, '00'x)
  364.     end
  365.     call charout , "."
  366.     do while (pos('0a'x, txt) > 0)
  367.         txt = strReplace(txt, '0a'x, '00'x)
  368.     end
  369.     call charout , "."
  370. /*    do while (pos("      ", txt) > 0)
  371.         txt = strReplace(txt, "      ", ' ')
  372.     end
  373.     call charout , "."
  374.     do while (pos("  ", txt) > 0)
  375.         txt = strReplace(txt, "  ", ' ')
  376.     end*/
  377.  
  378.     parse value SysTextScreenSize() with row col
  379.     scrwidth = col-2
  380.     lastchar = ""
  381.  
  382.     anchor = 0
  383.     bold = 0
  384.     italics = 0
  385.  
  386.     xpos = 0
  387.     level_ = 1
  388.     indent.level_ = 0
  389.     indentFirst.level_ = 0
  390.  
  391.     call charout, '0d0a1b'x||'[1A'||'1b'x||'[K'
  392.     call setColors
  393.     /* now go through the whole text on a per-character basis */
  394.     do p1 = 1 to length(txt)
  395.       ch = substr(txt, p1, 1)
  396.  
  397.       select
  398.         when (ch = "<") then do
  399.             /* HTML tag found */
  400.             p2 = pos('>', txt, p1)
  401.             tag = substr(txt, p1+1, p2-p1-1)
  402.             parse upper var tag cmd args
  403.             select
  404.                 when cmd = "!--" then do /* comment: skip following */
  405.                     p1 = pos("-->", txt, p1)+2 /* p1 will be set to p2 later on */
  406.                     iterate
  407.                 end
  408.                 when cmd = "HEAD" then do /* comment: skip following */
  409.                     p1 = pos("/HEAD>", translate(txt), p1)+5 /* p1 will be set to p2 later on */
  410.                     iterate
  411.                 end
  412.                 when (cmd = "BR") | (cmd = "TR") then
  413.                     call sayBreak
  414.                 when (cmd = "HR") then do
  415.                     call sayBreak
  416.                     call sayChar " "copies("─", scrWidth-(indent.level_))
  417.                 end
  418.                 when (cmd = "IMG") then do
  419.                     call sayChar imageString
  420.                     call setColors
  421.                 end
  422.                 when cmd = "P" then do
  423.                     call sayBreak
  424.                     call sayBreak
  425.                 end
  426.                 when (cmd = "A") & (pos("HREF=", translate(args)) > 0) then do
  427.                     anchor = 1
  428.                     call setColors
  429.                 end
  430.                 when cmd = "/A" then do
  431.                     anchor = 0
  432.                     call setColors
  433.                 end
  434.                 when (cmd = "B") then do
  435.                     bold = 1
  436.                     call setColors
  437.                 end
  438.                 when cmd = "/B" then do
  439.                     bold = 0
  440.                     call setColors
  441.                 end
  442.                 when (cmd = "I") then do
  443.                     italics = 1
  444.                     call setColors
  445.                 end
  446.                 when cmd = "/I" then do
  447.                     italics = 0
  448.                     call setColors
  449.                 end
  450.                 when cmd = "UL" then do
  451.                     oldlevel_ = level_
  452.                     level_ = level_+1
  453.                     indent.level_ = (indent.oldlevel_)+3
  454.                     indentFirst.level_ = (indentFirst.oldlevel_)+3
  455.                     do while (args \= "")
  456.                         parse upper var args arg1 args
  457.                         if substr(arg1, 1, 5) = "FIRST" then
  458.                             indentFirst.level_ = substr(arg1, 7)
  459.                         if substr(arg1, 1, 4) = "NEXT" then
  460.                             indent.level_ = substr(arg1, 6)
  461.                     end
  462.                 end
  463.                 when cmd = "/UL" then do
  464.                     oldlevel_ = level_
  465.                     level_ = level_-1
  466.                     if (level_ < 1) then level_ = 1
  467.                     else if (level_=1) then call sayBreak
  468.                 end
  469.                 when cmd = "LI" then do
  470.                     call sayBreak indentFirst.level_
  471.                 end
  472.                 when cmd = "TAB" then do
  473.                     if (xpos < indent.level_) then
  474.                         call sayChar copies(" ", (indent.level_)-xpos)
  475.                     else call sayBreak
  476.                     lastChar = " "
  477.                 end
  478.                 when cmd = "DBG" then
  479.                     say xpos
  480.                 otherwise /* ignore */
  481.             end /* select */
  482.             p1 = p2 /* skip processed characters */
  483.         end
  484.         when (ch = "&") & (substr(txt, p1+1, 1) \= " ") then do
  485.             /* special chars found */
  486.             p2 = pos(';', txt, p1)
  487.             code = substr(txt, p1+1, p2-p1-1)
  488.             p3 = pos(code||"=", escapeList.codepage)
  489.             if p3 > 0 then
  490.                 call sayChar substr(escapeList.codepage, pos("=", escapeList.codepage, p3)+1, 1)
  491.             p1 = p2 /* skip the processed chars */
  492.         end
  493.         when (ch = " ") | (ch = '00'x) then do
  494.                 /* space found: now check if following word still fits in line */
  495.                 charwise = 0
  496.                 p3 = min(pos(' ', txt, p1+1), pos('00'x, txt, p1+1))
  497.                 if (p3-p1-1 > 0) then do
  498.                     wrd = substr(txt, p1+1, p3-p1-1)
  499.                     lw = length(wrd)
  500.  
  501.                     p1_ = 0
  502.                     do forever
  503.                         p1_ = pos("<", wrd, p1_+1)
  504.                         if (p1_ > 0) then do
  505.                             p2_ = pos(">", wrd, p1_+1)
  506.                             lw = lw - (p2_-p1_)-1
  507.                             charwise = 1
  508.                         end
  509.                         else leave
  510.                     end
  511.  
  512.                     p3_ = 0
  513.                     do forever
  514.                         p3_ = pos("&", wrd, p3_+1)
  515.                         if (p3_ > 0) then do
  516.                             p4_ = pos(";", wrd, p3_+1)
  517.                             lw = lw - (p4_-p3_)
  518.                             charwise = 1
  519.                         end
  520.                         else leave
  521.                     end
  522.  
  523.                     /* lw now contains the "real" length of the word w/out tags and such */
  524.  
  525.                     if (xpos+lw > scrwidth) then do
  526.                         if (pos('<UL', wrd) = 0) & (pos('</UL', wrd) = 0) & (pos('<LI>', wrd) = 0) & (pos('<BR>', wrd) = 0) & (pos('<P>', wrd) = 0) then do
  527.                             call sayBreak
  528.                         end
  529.                         charwise = 1
  530.                     end
  531.                     else if (lastChar \= " ") then
  532.                          call sayChar " "
  533.                     if \charwise then do
  534.                          call sayChar wrd
  535.                          p1 = p1+length(wrd)
  536.                     end
  537.                 end /* if */
  538.         end /* when */
  539.         otherwise
  540.                 call sayChar ch
  541.       end /* select */
  542.     end /* do while */
  543.     call charout , nl||'1b'x'[0m'
  544. return
  545.  
  546. processExternalFile:
  547.     filename = arg(1)
  548.     txt = ""
  549.  
  550.     file = stream(filename, "c", "query exists");
  551.     if (file = "") then call charout , SysGetMessage(0002)
  552.     else do
  553.         fileLength = chars( file )
  554.         call stream file, "c", "OPEN READ"
  555.         txt = CharIn( file, 1, fileLength )
  556.         call stream file, "c", "CLOSE"
  557.     end
  558.     if (txt \= "") then
  559.         call msg txt
  560. return
  561.  
  562. extractMsg: procedure /* str = extractMsg(longstr, topic) */
  563.     msgFile = arg(1)
  564.     topic2 = arg(2)
  565.     str3 = "xhelp message file" msgFile "not found."
  566.     msgfile = sysSearchPath("PATH", msgFile)
  567.     if (msgFile \= "") then do
  568.         msgFileLength = chars( msgFile )
  569.         call stream msgFile, "c", "OPEN READ"
  570.         str3 = CharIn( msgFile, 1, msgFileLength )
  571.         call stream msgFile, "c", "CLOSE"
  572.         p1 = pos('<TOPIC NAME="'topic2'"', str3)
  573.         if (p1 > 0) then do
  574.             p2 = pos('>', str3, p1)+1
  575.             p3 = pos('</TOPIC>', str3, p2)
  576.             str3 = substr(str3, p2, (p3-p2))
  577.         end
  578.         else str3 = '0d0a'x'Help topic "'topic2'" not found in 'msgFile'.'||'0d0a'x
  579.     end
  580. return str3
  581.  
  582. getExtMsg:
  583.     msgName = arg(1)
  584.     country = value('HELP.COUNTRY',,'OS2ENVIRONMENT')
  585.     if country = "" then country="001"
  586.     str = extractMsg('XHELP'country'.MSG', msgName)
  587. return str
  588.  
  589. msg:
  590.     call charout , getExtMsg("analyzeMsg")
  591.     parse arg str
  592.     if pos("<HTML>", translate(str)) = 0 then do
  593.         call charout, '0d0a1b'x||'[1A'||'1b'x||'[K'
  594.         call charout , str
  595.     end
  596.     else do
  597.         do while (pos('&version;', str) > 0)
  598.            str = strReplace(str, '&version;', getExtMsg("versionString"))
  599.         end
  600.         cmd = arg(2)
  601.         if (cmd \= "") then
  602.             do while (pos('&cmd;', str) > 0)
  603.                 str = strReplace(str, '&cmd;', cmd)
  604.             end
  605.         call charout, '0d0a1b'x||'[1A'||'1b'x||'[K'
  606.         call sayHTML str
  607.     end
  608. return
  609.  
  610. ansiValue: procedure
  611.   normal = '1b'x'[0m'
  612.  
  613.   bright = 1
  614.   underline = 4
  615.   blink = 5
  616.  
  617.   black = 30
  618.   red = 31
  619.   green = 32
  620.   yellow = 33
  621.   blue = 34
  622.   magenta = 35
  623.   cyan = 36
  624.   white = 37
  625.  
  626.   litcolor = arg(1); ansicolor = ''; on = 0
  627.   do while litcolor \= ''
  628.      parse upper var litcolor item litcolor
  629.      if item = 'ON' then on = 10
  630.      else
  631.        ansicolor = ansicolor || ';' || value(item)+on
  632.   end /* do */
  633.  
  634. return '1b'x'['strip(ansicolor,'L',';')'m'
  635.  
  636.