home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / html_txt.zip / htm_txt2.cmd next >
OS/2 REXX Batch file  |  1999-03-09  |  79KB  |  2,634 lines

  1. /* 24 July 1998
  2.               HTM_TXT2.CMD : An HTML to text converter
  3.                               "the quicker version"
  4.  
  5.    Created by Daniel Hellerstein (danielH@econ.ag.gov)
  6.  
  7.    This program is freeware. It's written in REXX, and has been
  8.    tested under OS/2 4.0, and under the VCPI version of Regina REXX
  9.    for DOS.  Note that several io features are not available when
  10.    run under REGINA REXX (see HTML_TXT.HTM for details).
  11.  
  12. Features include:
  13.     Supports UL, OL, MENU ordered lists.
  14.     Supports nested TABLES, using line art to display.
  15.     FORM elements supported, including SELECT, TEXTAREA, and CHECKBOX.
  16.     A Hierarchical outline can be created from Hn elements
  17.     Highly configurable; logical element markers, list bullets,
  18.       outline numbering style, table writing styles, and many other
  19.       features are readily modified by changing user configurable parameters.
  20.     Fast (table intensive 60k file in 6 seconds on a P166)
  21.     Run from command line, or from a simple keyboard (non-gui) interface.
  22.  
  23. Installation:
  24.  
  25.   Just copy HTM_TXT2.CMD to any directory (for example, to a
  26.   directory in your PATH).
  27.   It runs a bit better with, but does NOT require, REXXUTIL.DLL
  28.  
  29.   Note:
  30.    This is the "faster" version of HTML_TXT. It does not have support
  31.    several advanced features; such as ROWSPAN and CAPTION for tables.
  32.    However, for many less complex pages, this will do an adequate 
  33.    job, in about 1/2 the time.
  34.  
  35.  
  36. Usage:
  37.  
  38.    Assuming HTM_TXT2.CMD is on your "x" drive; from an
  39.    os/2 command prompt enter:
  40.       x:>HTM_TXT2 file.htm file.txt
  41.    will convert the HTML document "file.htm" into an equivalent
  42.    text (ascii), and save the results as file.txt.
  43.  
  44.    Or, enter HTM_TXT2 at a command prompt, and answer the queries.
  45.  
  46.    See HTML_TXT.HTM for usage details -- there are a number of
  47.    options you may want to modify (though the defaults will work
  48.    fine in most cases).
  49.  
  50. Disclaimer:
  51.  
  52.    This is freeware that is to be used at your own risk -- the author
  53.    and any potentially affiliated institutions disclaim all responsibilties
  54.    for any consequence arising from the use, misuse, or abuse of
  55.    this software.
  56.  
  57.  
  58.    You may use this, or subsets of this program, as you see fit,
  59.    including for commercial  purposes; so long as  proper attribution
  60.    is made, and so long as such use does not preclude others from making
  61.    similar use of this code.
  62. */
  63.  
  64.  
  65. /********** USER CONFIGURABLE PARAMETERS *********/
  66. /* Note: there are 3 classes of parameters:
  67.        General controls
  68.        Table controls
  69.        Display characters  
  70.  
  71. The following parameters are of particular importance (that is, they
  72. may cure serious problems).
  73.  
  74.    NOANSI -- suppress use of ansi screen controls
  75.   LINEART -- suppress use of high ascii characters
  76.  TABLEMAXNEST and TABLEMODE2 -- use lists instead of nested tables   
  77.  TOOLONGWORD -- trim overly long strings (that have no spaces)
  78. */
  79.    
  80. /*  ----- General controls */
  81.  
  82.  
  83.  
  84.  
  85. /*CHARWIDTH: width of a character in pixels. 
  86.    Used to convert various WIDTH and HEIGHT attributes.  */
  87. charwidth=8
  88.  
  89. /* DOCAPS: Captialization is used for these "logical and physical" elements */
  90. docaps='TT CODE B STRONG '
  91.  
  92. /* DOULINE: Spaces are replaced with _ (uncerlines) for these "logical and 
  93.             physical elements" */
  94. douline='U BLINK'
  95.  
  96. /* DOQUOTE: "quotes" are used for "logical and physical" elements.
  97.   Note : QUOTESTRING1 and QUOTESTRING2 are used as the "quote" characters */
  98. doquote='I EM VAR'
  99.  
  100.  
  101. /*ERRORFLAG: String to place in output file when an error is found in the HTML code */
  102. errorflag='_ERROR_'
  103.  
  104. /* HN_OUTLINE: use numbered outline 
  105.    You can replace Hn elements  with a hierarchical outline.  
  106.    HN_OUTLINE says at what level of Hn to start.
  107.       1 : start at H1
  108.       2 : start at H2
  109.       3...7 : etc.
  110.       8   : never do outlining  
  111.    Note: see the HN_NUMBERS.n parameters for fine control of hierarchical outlininig*/
  112. hn_outline=2            
  113.  
  114. /* IGNORE_WIDTH: Ignore WIDTH in TABLE and TD elements 
  115.       2 : Ignore width, no autosizing (equi sized cells 
  116.       1 : Ignore WIDTH attributes in table (use all space, equally divided 
  117.       0 : Use WIDTH attributes  */
  118. ignore_width=0
  119.  
  120.  
  121. /* IMGSTRING: default words (or words) to use as an "image placeholder" 
  122.    This is used if a IMG element has no ALT attribute). */
  123. imgstring='[IMG]'
  124.  
  125. /* LINEART: Suppress use of high ascii (non keyboard) characters.
  126.             This is useful if you have a non-standard display.
  127.     -1 : No high ascii characters allows
  128.      0 : No lineart characters, but other high ascii characters are allowed
  129.      1 : Use high ascii characters   */
  130. lineart=1
  131.  
  132. /* LINELEN: maximum length of line (in characters). 
  133.             Larger values mean wider text files */
  134. linelen=80
  135.  
  136. /* NOANSI: Suppress use of ANSI screen controls.
  137.   This only effects screen io, not program functioning. If you see lots of 
  138.   $, [ and other garbage on your screen, set NOSANSI=1 
  139.      0 : do NOT suppress ANSI screen controls
  140.      1 : suppress ANSI screen controls */
  141. noansi=1   
  142.  
  143.  
  144. /* SHOWALLOPTS: display all OPTIONS in a SELECT list.
  145.    0 : Use the SIZE attrbute of a SELECT list
  146.    1 : Ignor SIZE attribute (always display all options) */
  147. showallopts=0   
  148.  
  149. /* SUPPRESS_BLANKLINES: minimize number of blank lines
  150.    1  : If multiple empty lines, just print one empty line (except if PRE)
  151.    0  : allow multiple empty lines  (i.e.; <BR><BR><BR> becomes 3 empty lines)*/
  152. suppress_blanklines=1
  153.  
  154. /* TOOLONG WORD: trimming long strings.
  155.   What to do with strings that don't fit (say, into a table cell)
  156.     -1 : trim (discard excess)
  157.      0 : wrap 
  158.      1 : push margins (does not apply to tables; for tables, 1 means trim) */
  159. toolongword=1     
  160.  
  161.  
  162. /* DISPLAY_ERRORS: note errors in text file 
  163.     0 : Do not note errors
  164.     1 : Note serious errors
  165.     2 :  Note all errors and warnings
  166.     3 : Long Note all errors, with
  167.    The "ERROR_FLAG" is used to "note errors" (it is written to the text file
  168.    near where the error was found. For 3, a short error description is also written*/
  169. display_errors=1
  170.  
  171. /*  ----- Table controls */
  172.  
  173. /* SUPPRESS_EMPTY_TABLE: display empty rows and empty tables
  174.      0  : do display (as blank lines)
  175.      1  : do not display */
  176. suppress_empty_table=1  
  177.  
  178. /* TABLEMODE: Suppress "tabular" display of tables:
  179.       1 :  use tabular display (possibly lineart)
  180.       2 :  use a UL list instead of tabluar display
  181.       3 :  use a HR like bar, P and BR instead of tabluar display*/
  182. tablemode=1     
  183.  
  184. /* TABLEMODE2: Suppress nested tables
  185.     Values (1, 2, 3) are same as for TABLEMODE.
  186.     Notes:
  187.        * only applies when TABLEMAXNEST is sufficiently small. 
  188.        * never used if TABLEMODE>1   */
  189. tablemode2=1    
  190.  
  191. /* TABLEMAXNEST: When to apply TABLEMODE2
  192.    At what "level of nesting" should TABLEMODE2 be used. 
  193.       0 : Use for all "nested tables" (tables within tables)
  194.       1 : Use for "tables within tables within tables"
  195.       2, 3, etc. : Larger numbers mean more nested tables are displayed.
  196.   Note: you may need to set this to 0 if you are using Regina REXX */
  197. tablemaxnest=3 
  198.  
  199. /* TABLEBORDER: type of default table borders
  200.       0 : default is no border -- can be overridden by a BORDER=n attribute in <TABLE>
  201.       1 : default is narrow border -- can be overridden by a BORDER=n attribute in <TABLE>
  202.     1.1 : always use narrow border 
  203.   2 and above: Use broad border. */
  204. tableborder=0
  205.  
  206. /*  ----- Display Characters */
  207.  
  208. /* You can specify either the actual character (in single quotes)
  209.    or an ascii value (i.e.; 48 would mean '0'). 
  210.    For example: 
  211.          RADIOBOX='X' and RADIOBOX=88 are equivalent.
  212.         
  213.    Notes: 
  214.       * for high ascii (values > 127), the character displayed may depend
  215.          on the code page your computer uses.
  216.       * if lineart=-1, high ascii values will not be used (if you
  217.         specify a high ascii value, a default character will be used
  218.         instead).
  219.       * if lineart=0, high ascii values can be specified, but not for lineart.
  220.       * in many cases, these characters are used to "quote" strings that
  221.         would be displayed using fonts (say, italics, large bold headers,
  222.         or colored links).
  223. */
  224.  
  225. /* CHECKBOX: Character used as to signify an <INPUT TYPE=CHECKBOX .. > element
  226.    CHECKBOXCHECK: Character used as to signify an 
  227.                     <INPUT TYPE=CHECKBOX .. CHECKED> element */
  228. checkbox=176
  229. checkboxcheck=178
  230.  
  231. /* FLAGMENU: bullets used in MENU list. 
  232.     You can specify characters and/or ascii numbers. If the "level" of menus exceeds
  233.     the words in flagmenu, the first character is used for these "excess" levels. */
  234. flagmenu='#'
  235.  
  236. /* FLAGUL : bullets used in UL list.
  237.      As with flagmenu, first character is used in "excess" levels */
  238. flagul='@ ~ $ '
  239.  
  240. /* FLAGTL : bullets used with UL lists, when UL lists is used instead of a TABLE 
  241.      As with flagmenu, first character is used in "excess" levels */
  242. flagtl='176 177 178 220 224'
  243.  
  244. /* FLAGSELECT: character used before an OPTION (in a SELECT list)
  245.    FLAGSELECT2: character used for a "selected OPTION" (in a SELECT list) */
  246. flagselect='?'
  247. flagselect2='x'
  248.  
  249. /* HN_NUMBERS.n: characters to use in outlining
  250.    These are used with the "nth level" of an Hn outline. 
  251.    Notes:
  252.     *   hn_numbers.1 refers to the "first outline" -- if HN_OUTLINE=2, then these 
  253.         are used with H2 (that is, H1 is NOT subject to outline numbering).
  254.     *   if the number of outline numbers exceeds the words in a hn_numbers.n list,
  255.         standard numbers (i.e.; 27, 28, ...) are used  */
  256. hn_numberS.1='I II III IV V VI VII VIII IX X XI XII XIII XIV XV XVI XVII XVIII IXX XX XX XXI XXII XXIII XXIV XXV XXVI'
  257. hn_numberS.2='a b c d e f g h i j k l m n o p q r s t u v w x y z '
  258. hn_numbers.3='1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 '
  259. hn_numberS.4='i ii iii iv v vi vii viii ix x xi xii xiii xiv xv xvi xvii xviii ixx xx xx xxi xxii xxiii xxiv xxv xxvi'
  260. hn_numbers.5='1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 '
  261. hn_numbers.6='1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 '
  262. hn_numbers.7='1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 '
  263.  
  264. /* HRBIG: character to use if SIZE>1 in an <HR ..> element */
  265. hrbig=220
  266.  
  267.  
  268. /* OL_NUMBERS: Characters (i.e.; roman numerals, standard digits, letters) in OL lists.
  269.    If number of elements in a list exceeds the number of words in ol_numbers, standard
  270.    numbers are used (i.e.; 11, 12, ...) */
  271. ol_numbers='1 2 3 4 5 6 7 8 9 10 '  
  272.  
  273.  
  274. /* PRETITLE: short string to place before the "document title"
  275.    POSTTITLE: short string to place after the "document title" */
  276. PRETITLE='   ***   '
  277. POSTTITLE='   ***   '
  278.  
  279. /* PREA: character used before <A> anchors
  280.    POSTA: character used after <A> anchors */
  281. PREA=174
  282. POSTA=175
  283.  
  284. /* PREH1 : character used before <H1> 
  285.    POSTH1 : character used after <H1> */
  286. preh1='* '
  287. posth1=' *'
  288.  
  289. /* PREHN : character used before H2 ... H7  
  290.    POSTHN : character used after H2 ... H7 */
  291. prehn=' '
  292. posthn=' '
  293.  
  294. /* PREIMG: character to place before an  "image placeholder" (the ALT attribute of <IMG ..>
  295.    POSTIMG: character to place after and "image placeholder" */
  296. preimg=' ['
  297. postimg='] '
  298.  
  299.  
  300. /* QUOTESTRING1: character used as a "left quote" (with doquote elements)
  301.    QUOTESTRING2: character used as a "right quote" (with doquote elements) */
  302. quotestring1=180
  303. quotestring2=195
  304.  
  305.  
  306. /* RADIOBOX: Character used as to signify an <INPUT TYPE=RADIO .. > element
  307.    RADIOBOXCHECK: Character used as to signify an 
  308.                     <INPUT TYPE=RADIO .. CHECKED> element */
  309. radiobox=176
  310. radioboxcheck=178
  311.  
  312. /* SUBMITMARK1: Character to use before a <INPUT TYPE=SUBMIT or TYPE=RESET ..> element 
  313.    SUBMITMARK2: Character to use after a <INPUT TYPE=SUBMIT or TYPE=RESET ..> element */
  314. submitmark1=204
  315. submitmark2=185
  316.  
  317.  
  318. /* TEXTMARK1 : character to use on left end of an <INPUT TYPE=TEXT ..> element
  319.    TEXTMARK2 : character to use on right end of an <INPUT TYPE=TEXT ..> element
  320.    TEXTMARK : character to use inside of  an <INPUT TYPE=TEXT ..> element  */
  321. textmark1=222
  322. textmark2=221
  323. textmark='_'
  324.  
  325. /* TABLEVERT: character to use as vertical lines in a table
  326.    TABLEHORIZ: character to use as horizontal lines in a table
  327.    Neither of these are used if LINEART=1  */
  328. tablevert='!'      
  329. tablehoriz='-'
  330.  
  331. /* TABLEFILLER: character to used to fill empty spaces in tables and textbox's */
  332. tablefiller=' '
  333.  
  334. /********** END OF USER CONFIGURABLE PARAMETERS *********/
  335.  
  336.  
  337. call loadlibs           /* load up some libraries and ANSI support*/
  338.  
  339. parse arg infile outfile params
  340.  
  341. if abbrev(translate(infile),'/VAR')=1 then do
  342.     params='/VAR 'outfile' 'params
  343.     outfile='' ; infile=' '
  344. end /* do */
  345.  
  346. if abbrev(translate(outfile),'/VAR')=1 then do
  347.     outfile=''
  348.     params='/VAR  'params
  349. end /* do */
  350.  
  351.  
  352.  
  353. forceout=0
  354. if outfile<>'' then forceout=1
  355.  
  356. if params<>'' then do
  357.    call change_params params     /* change parameters (globals) */
  358. end /* do */
  359.  
  360. if noansi=0 then call loadlibs
  361.  
  362.  
  363. getin:
  364. if infile="" then do
  365.     call lineout,bold " Enter name of HTML file (? for help, EXIT to quit) "normal
  366.     call charout,"  "reverse " :" normal
  367.     pull infile ; infile=strip(translate(infile))
  368. end
  369.  
  370. if strip(translate(infile))='EXIT' then do
  371.    say "bye "
  372.    exit
  373. end /* do */
  374.  
  375. if infile=' ' | strip(infile)='?' then do
  376.    call sayhelp
  377.    infile=''
  378.    signal getin
  379. end /* do */
  380.  
  381. if abbrev(translate(strip(infile)),'/DIR')=1 then do
  382.     infile=substr(strip(infile),2)
  383.     address cmd infile
  384.     infile=''
  385.     signal getin
  386. end /* do */
  387.  
  388.  
  389. if abbrev(translate(strip(infile)),'/VAR')=1 then do
  390.   call change_params infile
  391.   infile=''
  392.   signal getin
  393. end
  394.  
  395. /* maybe it's actually a file name */
  396.  
  397. htmlfile=stream(infile,'c','query exists')              /* does it, or .html or .htm version of it, exist*/
  398. if htmlfile='' then htmlfile=stream(infile||'.HTM','c','query exists')
  399. if htmlfile='' then htmlfile=stream(infile||'.HTML','c','query exists')
  400.  
  401. if htmlfile='' then do
  402.     Say "Sorry. could not find: " infile
  403.     exit
  404. end /* do */
  405.  
  406. htmllen=stream(htmlfile,'c','query size')
  407. if htmllen=0 then do
  408.    say " Sorry -- " htmlfile " is empty "
  409.    infile=''
  410.    signal getin
  411. end /* do */
  412. stuff=charin(htmlfile,1,htmllen)
  413. Say "Reading " HTMLlen " characters from " htmlfile
  414.  
  415. outget: nop
  416. if outfile='' then do
  417.    parse var htmlfile tout '.' .
  418.    tout=tout||'.TXT'
  419.    say " "
  420.    say bold " Enter name of output file (ENTER="tout")"normal
  421.    call charout,"  "reverse " :" normal
  422.    parse pull outfile
  423.    if outfile='' then outfile=tout
  424. end /* do */
  425.  
  426. foo=stream(outfile,'c','query size')
  427. if foo='' then foo=0
  428.  
  429. signal off syntax ; signal off error
  430. signal on syntax name hoy1 ; signal on error name hoy1
  431. if foo<>0 then do
  432.      if forceout=0 then do
  433.         if yesno("Overwrite? ")=0 then do
  434.             outfile='' ; signal outget
  435.        end /* do */
  436.      end                /* else, command line mode implies overrwrite */
  437.      else do
  438.           say "Overwriting "foo
  439.      end /* do */
  440.      foo=sysfiledelete(outfile)
  441.      if foo<>0 then do
  442.             say "Could not delete (error " foo
  443.             outfile=''
  444.             signal outget
  445.      end /* do */
  446. end /* do */
  447. signal off syntax ; signal off error
  448. signal hoy2
  449.  
  450. hoy1:
  451. outfile=' '
  452. say " % " sigl " : " rc
  453. say "File exists. Try another name"
  454. signal off syntax ; signal off error
  455. signal outget
  456.  
  457.  
  458. hoy2:
  459. /* get HEAD and BODY */
  460. atitle=head_body(stuff)
  461.  
  462.  
  463. /* write <TITLE> */
  464. atitle=pretitle||atitle||posttitle
  465. if length(atitle)<linelen then atitle=center(atitle,linelen)
  466. call lineout2 outfile,atitle
  467. call lineout outfile,' '
  468.  
  469.  
  470. /* find all <IMG links and convert to ALT tag, or to IMGSTRING */
  471. call img_convert imgstring
  472.  
  473. /* remove APPLET  etc junk */
  474. foo=remove_applet('APPLET')
  475. foo=remove_applet('OBJECT')
  476. foo=remove_applet('EMBED')
  477.  
  478. call set_vars           /* check and set display characters */
  479.  
  480.  
  481. /* start parsing BODY */
  482.  
  483. linelen_orig=linelen
  484. wasblank=0
  485. indent=0                /* current indent */
  486. rightindent=0
  487. ispre=0                 /* <PRE> is on? */
  488. olcnts=''                 /* OL count */
  489. lastelem=''
  490. capon=0
  491. ulineon=0
  492. listtypes=''
  493. anchoron=0 ; anchoron1=0 ; ANCHORON2=0
  494. quoteon=0 ; quoteon1=0 ; QUOTEON2=0
  495. ddon=0
  496. thispara=''             /* current paragraph */
  497. iscenter=0
  498. sendout_internal=0
  499.  
  500. if hn_outline>0 then do
  501.   do jj=hn_outline to 7
  502.      hn_outlines.jj=0
  503.   end /* do */
  504. end
  505.  
  506. iat=htmllen-length(body)
  507. say bold " Converting HTML to Text " normal " ...... "
  508. prenote=reverse||'   : '||normal
  509. if htmllen>15000 then call charout, prenote
  510.  
  511. etime=time('r')
  512.  
  513. do forever
  514.     if body='' then leave
  515.     if htmllen>15000 then iat=noteit(htmllen-length(body),iat,10000,prenote)
  516.  
  517.  
  518.     parse var body t1 '<' t2a '>' body
  519.  
  520.     T1=CONVERT_CODES(T1,CAPON,ISPRE,ULINEON)
  521.  
  522.     t1=fix_quote_anchor(t1)  /* may change globals */
  523.  
  524.  
  525. /* Ready to add more content ..... */
  526.      thispara=thispara||t1      /* ADD T1 TO THISPARA FOR EVENTUAL OUTPUT */
  527.  
  528. /* now prepare to process this <element> (T2 is first word, T2A is all words */
  529.     t2=strip(translate(word(t2a,1)))             /* get rid of element modifiers */
  530.     if left(t2,1)='/'  then
  531.         t2end=substr(t2,2)
  532.     else
  533.         t2end=''
  534.  
  535. /* a check: convert table to something else (works on globals? */
  536.     t2=cvt_table_elements(t2,1)
  537.  
  538.  
  539. /* Now, process this ELEMENT */
  540.    if T2='TABLE' then DO            /* table -- LOTS OF WORK! */
  541.          foo=sendout(thispara,ispre,indent,aflag)
  542.          thispara='';aflag=0
  543.          call sendout ' '
  544.          AA=DO_TABLE(t2a)
  545.          sendout_internal=1
  546.          abb=gen_table(1,linelen-(indent+rightindent))
  547.          sendout_internal=0
  548.          if tables.1.!errors<>'' then
  549.               call do_display_error 0,'Table ERRORS: '||tables.1.!errors,tables.1.!errors
  550.          foo=sendout(abb,1)
  551.    end /* do */
  552.    else do              /* NOT a table -- interpret this element (sets globals */
  553.          call interpret_elems linelen   /* changes globals */
  554.    end
  555.  
  556. end             /* do foerver -- until no more stuff in BODY  */
  557.  
  558. /* dump current paragraph */
  559. foo=sendout(thispara,ispre,indent,aflag)
  560.  
  561. /* and we are done! */
  562.  
  563.  
  564. call lineout outfile
  565.  
  566. etime=time('e')
  567. say ' '
  568. say "Elapsed time: " etime
  569.  
  570. exit
  571.  
  572.  
  573. /*************** END OF MAIN **************/
  574.  
  575. /******************************/
  576. /* change parameters */
  577. change_params:
  578. parse arg plist
  579.  
  580. plist_ok='TOOLONGWORD TABLEMODE TABLEMODE2 TABLEBORDER PRETITLE POSTTITLE ' ,
  581.          ' LINELEN PREA POSTA PREH1 POSTH1 PREHN POSTHN IMGSTRING PREIMG POSTIMG ',
  582.          ' DOCAPS DOULINE DOQUOTE QUOTESTRING1 QUOTESTRING2 HN_OUTLINE ' ,
  583.          ' HN_NUMBERS.1 HN_NUMBERS.2 HN_NUMBERS.3 HN_NUMBERS.4 HN_NUMBERS.5 HN_NUMBERS.6 ',
  584.          ' HN_NUMBERS.7 OL_NUMBERS FLAGMENU FLAGUL FLAGTL FLAGSELECT FLAGSELECT2 ',
  585.          ' RADIOBOX RADIOBOXCHECK CHECKBOXK CHECKBOXCHECK TEXTMARK1 TEXTMARK2 TEXTMARK ',
  586.          ' HRBIG SUBMITMARK1 SUBMITMARK2 LINEART TABLEHORIZ TABLEFILLER SHOWALLOPTS ' ,
  587.          ' ERRORFLAG  NOANSI TABLEMAXNEST CHARWIDTH SUPPRESS_BLANKLINES DISPLAY_ERRORS ' ,
  588.          ' IGNORE_WIDTH '
  589.  
  590. PLIST=STRIP(PLIST) ; PLIST=SUBSTR(PLIST,5)
  591.  
  592. do forever
  593.    if plist='' then leave
  594.    PARSE VAR PLIST AVAR '=' AVAL ';' PLIST
  595.    AVAR=STRIP(TRANSLATE(AVAR))
  596.    IF WORDPOS(AVAR,PLIST_OK)=0 then DO
  597.        SAY "Parameter Error: no such parameter= "avar
  598.        iterate
  599.    end /* do */
  600.    if datatype(strip(aval))='NUM' then aval=strip(aval)
  601.    oldval=value(avar)
  602.    foo=value(avar,aval)
  603.    say " Changing "avar" from "reverse||oldval||normal' to 'bold||aval||normal
  604. end /* do */
  605. return 1
  606.  
  607.  
  608.  
  609.  
  610. /*************/
  611. /* write a box around a string. Use lineart, or ascii characters */
  612. /* box if no ncols, then use width of longest line */
  613. /* if ncols, cut longest line at ncols */
  614. box_around:procedure expose  lineart tablefiller
  615. parse arg ah,ncols
  616. crlf='0d0a'x
  617. if ncols="" then do     /* no length -- use length of longest line */
  618.    smot=ah ; ncols=0
  619.    do forever
  620.       if smot='' then leave
  621.       parse var smot al1 (crlf) smot
  622.       ncols=max(max,length(al1))
  623.    end /* do */
  624. end /* do */
  625.  ahz='_' ; avt='|'
  626.  ah2='   'copies(ahz,ncols+1)||crlf
  627.  if lineart=1 then do
  628.        ahz=d2c(196) ; avt=d2c(179)
  629.        ah2=' 'd2c(218)||copies(ahz,ncols)||d2c(191)||crlf
  630.  end
  631.  do until ah=''
  632.         parse var ah  aline (crlf) ah
  633.         aline=left(aline,ncols,tablefiller)
  634.         if lineart=1 then
  635.               ah2=ah2' 'avt||aline||avt
  636.         else
  637.               ah2=ah2' 'avt' 'aline' 'avt
  638.         if ah<>'' then ah2=ah2||crlf
  639.   end /* do */
  640.   if lineart=1 then
  641.           ah2=ah2||crlf||' 'd2c(192)||copies(ahz,ncols)||d2c(217)||crlf
  642.   else
  643.          ah2=ah2||crlf'   'copies(ahz,ncols+1)||crlf
  644.  
  645.   return ah2
  646.  
  647.  
  648. /*******************/
  649. /* a "list flag" needed? */
  650. figflag:procedure expose olcnts flagul flagmenu listtypes ol_numbers flagtl
  651.  
  652.  if listtypes='' then return ''
  653.  IW=WORDS(LISTTYPES)
  654.   LASTT=WORD(LISTTYPES,IW)
  655.  
  656. select
  657.   when lastt='UL' then aflag=nth_word(flagul,iw)
  658.   when lastt='TL' then aflag=nth_word(flagtl,iw)
  659.   when lastt='MENU' | lastt='DIR' then aflag=nth_word(flagmenu,iw)
  660.   when lastt='OL' then do
  661.      iw2=words(olcnts)
  662.      io2=strip(word(olcnts,iw2))
  663.      io2=io2+1
  664.      if io2>words(ol_numbers) then
  665.         aflag=io2+1
  666.      else
  667.         aflag=strip(word(ol_Numbers,io2))
  668.      aflag=aflag'.'
  669.      olcnts=delword(olcnts,iw2)' 'io2
  670.   end /* do */
  671.   otherwise nop
  672. end  /* select */
  673.  
  674. return aflag
  675.  
  676.  
  677.  
  678. /***********************************/
  679. img_convert:
  680. parse arg imgs
  681.  
  682. say bold " Converting <IMG> elements ... " normal
  683. stuff2=''
  684. iat=1
  685. tbody=translate(body)
  686. do forever
  687.   iat2=pos('<IMG',tbody,iat)
  688.   if iat2=0 then leave          /* all done */
  689.  
  690. /* found an IMG element. Extract it, modify body */
  691.    iat3=pos('>',body,iat2)
  692.     imgis=substr(body,iat2+4,iat3-(iat2+4))
  693.     imgnAme=imgs
  694.     if imgs=0 then do
  695.        imgname=' ' ; imgis=''
  696.     end /* do */
  697.     else do
  698.        imgname=get_elem_val(imgis,'ALT')
  699.     end
  700.     IF IMGNAME<>' ' THEN 
  701.          imgname=preimg||imgname||postimg
  702.     else
  703.         imgname=imgs
  704.     abody=left(body,iat2-1)||imgname
  705.     iat=length(abody)
  706.     body=abody||substr(body,iat3+1)
  707.     tbody=abody||substr(tbody,iat3+1)
  708. end
  709.  
  710. return 1
  711.  
  712.  
  713.  
  714.  
  715. /****************/
  716. /* set global vars */
  717. set_vars:
  718. crlf='0d0a'x
  719. aflag=0
  720.  
  721. tablefiller=do_d2c(tablefiller,' ')
  722. tablevert=do_d2c(tablevert,'|')
  723. tablehoriz=do_d2c(tablehoriz,'_')
  724.  
  725. hrbig=do_d2c(hrbig,'=')
  726.  
  727. quotestring1=do_d2c(quotestring1,'`')
  728. quotestring2=do_d2c(quotestring2,"`")
  729.  
  730. radiobox=do_d2c(radiobox,'o')
  731. checkbox=do_d2c(checkbox,'O')
  732. radioboxcheck=do_d2c(radioboxcheck,'x')
  733. checkboxcheck=do_d2c(checkboxcheck,'x')
  734.  
  735. flagselect=do_d2c(flagselect,'?')
  736. flagselect2=do_d2c(flagselect2,'x')
  737.  
  738. submitmark1=do_d2c(submitmark1,'{')
  739. submitmark2=do_d2c(submitmark2,'}')
  740.  
  741. textmark1=do_d2c(textmark1,'[')
  742. textmark2=do_d2c(textmark2,']')
  743. textmark=do_d2c(textmark,'_')
  744.  
  745.  
  746. prea=do_d2c(prea,'<')
  747. posta=do_d2c(posta,'>')
  748. preh1=do_d2c(preh1,':')
  749. posth1=do_d2c(posth1,':')
  750. prehn=do_d2c(prehn,':')
  751. posthn=do_d2c(posthn,':')
  752.  
  753. preimg=do_d2c(preimg,'[')
  754. postimg=do_d2c(postimg,'[')
  755.  
  756. flagul=do_d2c(flagul,'*',1)
  757. flagmenu=do_d2c(flagmenu,'@',1)
  758. flagtl=do_d2c(flagtl,'=',1)
  759.  
  760. return 1
  761.  
  762.  
  763.  
  764. /***********************************/
  765. /* get string ending with /TOFIND */
  766. getelem:
  767. parse upper arg tofind
  768. tofind=strip(tofind)
  769. foo=pos('<'||tofind,translate(body))
  770. p1=left(body,foo-1)
  771. parse var body . '>' body
  772. return p1
  773.  
  774.  
  775. /********/
  776. /* remove < > from a string */
  777. remove_htmls:procedure
  778. parse arg ast
  779.  
  780. ast0=''
  781. do forever
  782.   if ast='' then leave
  783.   parse var ast v1 '<' v2 '>' ast
  784.   ast0=ast||v1
  785. end /* do */
  786. return ast0
  787.  
  788.  
  789.  
  790. /***********************************/
  791. /* dump something to output file */
  792. sendout:procedure expose linelen outfile rightindent iscenter toolongword ,
  793.                  sendout_internal sendout_var suppress_blanklines wasblank
  794.  
  795. parse arg toput,ispre,indent,aflag,XLINELEN
  796. crlf='0d0a'x
  797. IF XLINELEN="" THEN XLINELEN=LINELEN
  798.  
  799. if (ispre='' | ispre=0)& toput=''  then do
  800.   if suppress_blanklines=1 & wasblank=1 then do
  801.       return 1           /* ignore this "extra crlf */
  802.   end
  803.   if sendout_internal<>1 then do
  804.       call lineout2 outfile,toput
  805.   end
  806.   else do
  807.       sendout_var=sendout_var||toput||crlf
  808.   end
  809.   wasblank=1            /* signal "we just did a crlf (ignored if suppress_blanklines<>1 */
  810.   return 1
  811. end
  812.  
  813. wasblank=0              /* not a crlf, or a <PRE> crlf */
  814.  
  815.  
  816. /* PRE-- send as is (with possible margin clipping */
  817. if  ispre=1 then do
  818.   if toolongword<1 then do
  819.     toput0=''
  820.     do forever
  821.       if toput='' then leave
  822.       parse var toput aline (crlf) toput
  823.       aline=fix_linelen(aline,Xlinelen,toolongword)
  824.       toput0=toput0||aline
  825.       if toput<>'' then do
  826.          toput0=toput0||crlf
  827.        end
  828.     end
  829.     toput=toput0
  830.   end
  831.   if sendout_internal<>1 then do
  832.       call lineout2 outfile,toput
  833.   end
  834.   else do
  835.       sendout_var=sendout_var||toput||crlf
  836.   end
  837.   return 1
  838. end
  839.  
  840. /* pre, with indent */
  841. if ispre=2 then do
  842.   toput0=''
  843.   do forever
  844.       if toput='' then leave
  845.       parse var toput aline (crlf) toput
  846.       aline=fix_linelen(copies(' ',indent)||aline,Xlinelen,toolongword)
  847.       toput0=toput0||aline
  848.       if toput<>'' then toput0=toput0||crlf
  849.   end
  850.  
  851.   toput=toput0
  852.   if sendout_internal<>1 then do
  853.       call lineout2 outfile,toput
  854.   end
  855.   else do
  856.       sendout_var=sendout_var||toput||crlf
  857.   end
  858.   return 1
  859. end
  860.  
  861. if aflag=0 & toput='' then return 1
  862.  
  863.  
  864. if indent='' then indent=0
  865. if indent<0 | indent>(Xlinelen-1) then indent=0
  866. anindent=''
  867. if indent>0 then anindent=copies(' ',indent)
  868. anindent1=anindent
  869.  
  870. if aflag<>0 then do
  871.   if indent>=(length(aflag)+1) then do
  872.        indent=indent-length(aflag)
  873.        anindent1=copies(' ',indent)||aflag||' '
  874.        anindent=anindent' '
  875.    end
  876. end /* do */
  877.  
  878.  
  879. linelenl=Xlinelen-(rightindent)    /* shorten linelen if blockquote is on */
  880. /* remove extra spaces and crlfs */
  881. toput=translate(toput,' ','0d0a0009'x)
  882. toput=space(toput,1)
  883. toput=translate(toput,' ','01'x)  /* hack used for &Nbsp */
  884.  
  885. if (length(toput)+indent) <linelenl then do  /* short string -- write it */
  886.      if iscenter=1 then do      /* center it*/
  887.          isleft=Xlinelen-length(anindent1)
  888.          toput=center(toput,isleft)
  889.      end
  890.      if iscenter=2 then do      /* right it*/
  891.          isleft=Xlinelen-length(anindent1)
  892.          toput=right(toput,isleft,' ')
  893.      end
  894.  
  895.  
  896.      if sendout_internal<>1 then
  897.        call lineout2 outfile,anindent1||toput
  898.      else
  899.         sendout_var=sendout_var||anindent1||toput||crlf
  900.  
  901.      return 1
  902. end /* do */
  903.  
  904. /* else, parse into linelen chunks and write out */
  905. aline=anindent1
  906. do forever
  907.    if toput='' then leave
  908.    parse var toput aword toput
  909.    lenword=length(aword)
  910.  
  911.    if lenword>linelenl then do /* BIG word */
  912.        if aline<>'' then do
  913.          if iscenter=1 then aline=center(aline,Xlinelen)
  914.          if iscenter=2 then aline=right(aline,Xlinelen)
  915.  
  916.  
  917.          if sendout_internal<>1 then
  918.              call lineout2 outfile,aline
  919.          else
  920.              sendout_var=sendout_var||aline||crlf
  921.        end
  922.        aword=fix_linelen(aword,Xlinelenl,toolongword)
  923.  
  924.  
  925.        if sendout_internal<>1 then
  926.               call lineout2 outfile,aword
  927.         else
  928.              sendout_var=sendout_var||aword||crlf
  929.  
  930.        aline=anindent
  931.        iterate
  932.    end /* do */
  933.  
  934.    if (length(aline)+lenword)>linelenl then do /* line + word too long */
  935.        if iscenter=1 then  aline=center(aline,Xlinelen)
  936.        if iscenter=2 then aline=right(aline,Xlinelen)
  937.  
  938.        if sendout_internal<>1 then
  939.           call lineout2 outfile,aline
  940.        else
  941.            sendout_var=sendout_var||aline||crlf
  942.        aline=anindent
  943.    end /* do */
  944.  
  945.    aline=aline||aword||' '      /* append this word to current line */
  946.  
  947. end /* do */
  948. if aline<>''  then  do
  949.   if iscenter=1 then  aline=center(aline,Xlinelen)
  950.   if iscenter=2 then aline=right(aline,Xlinelen)
  951.   aline=fix_linelen(aline,Xlinelen,toolongword)
  952.  
  953.   if sendout_internal<>1 then
  954.      call lineout2 outfile,aline
  955.   else
  956.      sendout_var=sendout_var||aline||crlf
  957. end
  958. return 1
  959.  
  960.  
  961. /*************************************/
  962. /* remove <APPLET> ... </APPLET>  */
  963. remove_applet:procedure expose body
  964. parse upper arg badelem
  965.  
  966. do forever  /* exit with RETURN */
  967.    tbody=translate(body)                /* not real efficient, but easy */
  968.    app1=pos('<'badelem,tbody,1)
  969.    if app1=0 then return 0
  970.    app2=pos('</'||badelem,tbody,app1+5)
  971.    if app2=0 then do
  972.         say ' '
  973.         say " Warning: no /"badelem ' element '
  974.         return 0
  975.    end /* do */
  976.    body2=substr(body,app2+5)
  977.    body=left(body,app1-1)
  978.    parse var body2 . '>' body2
  979.    body=body||body2
  980. end
  981.  
  982.  
  983. /*************************************/
  984. /* REMOVE HTML COMMENTS, fix up <  x  elements, parse into HEAD and BODY sections (globals ) */
  985. head_body:PROCEDURE expose head body normal reverse bold prenote
  986. PARSE ARG STUFF
  987.  
  988. /* remove html comments */
  989. say bold " Removing comments ... " normal
  990. body="" ;iat=0
  991. prenote=reverse||'   : '||normal
  992.  
  993. do forever              /*no comments within comments are allowed */
  994.    if stuff="" then leave
  995.    parse var stuff t1 '<!--' t2 '-->' stuff
  996.    body=body||t1
  997. end /* do */
  998.  
  999. /* convert < x to <x, where space can be space, tab, crlf */
  1000. say bold " Cleaning up elements " normal
  1001. stuff=body
  1002. body='' ;iat=0
  1003. do forever
  1004.   if stuff="" then leave
  1005.   parse var stuff t1 '< ' t2 '>' stuff
  1006.   body=body||t1
  1007.   if t2<>''  then do
  1008.     t2=translate(t2,' ','0d0a0900'x)
  1009.     t2=strip(t2)
  1010.     if t2<>'' then body=body||'<'||t2||'>'
  1011.   end
  1012. end /* do */
  1013.  
  1014.  
  1015. say bold " Extracting <HEAD> and <BODY> " normal
  1016. /* pull out <HEAD> and <BODY> sections */
  1017. stuff=body ;iat=0
  1018. body='' ; head='' ; iat=0
  1019. headon=0; bodyon=0 ; headon2=0; bodyon2=0
  1020.  
  1021. tstuff=translate(stuff)
  1022. hd1=pos('<HEAD',tstuff,1)
  1023. hd2=pos('</HEAD',tstuff,max(hd1,1))
  1024.  
  1025. if hd1=0 then say "Warning: no <HEAD> element "
  1026. if hd2=0 then say "Warning: no </HEAD> element "
  1027.  
  1028. if hd2>0 then do
  1029.    hdlen=hd2-(hd1+5)  /*  <HEAD starts at 10, then read from 10+5 */
  1030.    head=substr(stuff,hd1,hdlen)
  1031.    parse var head . '>' head   /* get rid of remnand  > */
  1032. end /* do */
  1033.  
  1034. hd2=hd2+6  /* get by /HEAD */
  1035.  
  1036. bd1=pos('<BODY',tstuff,hd2)
  1037. bd2=pos('</BODY',tstuff,max(bd1+5,hd2))
  1038.  
  1039. if bd1=0 then say "Warning: No <BODY> element "
  1040. if bd2=0 then say "Warning: No <HEAD> element "
  1041.  
  1042. if bd1=0 then bd1=max(bd1+5,hd2)
  1043. if bd2=0 then bd2=length(tstuff)+1
  1044. bdlen=bd2-bd1
  1045. body=substr(stuff,bd1,bdlen)
  1046.  
  1047.  
  1048. /* extract TITLE  from HEAD */
  1049. do forever
  1050.    if head="" then leave
  1051.    parse var head t1 '<' t2 '>' head
  1052.    t2a=strip(translate(word(t2,1)))
  1053.    if t2a="TITLE" then do
  1054.       parse var head title '<' .
  1055.       return title
  1056.    end /* do */
  1057. end /* do */
  1058.  
  1059. return ' '
  1060.  
  1061.  
  1062.  
  1063.  
  1064. /***************/
  1065. /* return 0 for no, 1 for yes, default otherwise */
  1066. is_yes_no:procedure
  1067. parse arg aval,def
  1068. tdef=strip(translate(aval))
  1069. if wordpos(tdef,'Y YES 1')>0 then return 1
  1070. if wordpos(tdef,'N NO 0')>0 then return 0
  1071. return def
  1072.  
  1073.  
  1074.  /* ------------------------------------------------------------------ */
  1075.  /* function: Check if ANSI is activated                               */
  1076.  /*                                                                    */
  1077.  /* call:     CheckAnsi                                                */
  1078.  /*                                                                    */
  1079.  /* where:    -                                                        */
  1080.  /*                                                                    */
  1081.  /* returns:  1 - ANSI support detected                                */
  1082.  /*           0 - no ANSI support available                            */
  1083.  /*          -1 - error detecting ansi                                 */
  1084.  /*                                                                    */
  1085.  /* note:     Tested with the German and the US version of OS/2 3.0    */
  1086.  /*                                                                    */
  1087.  /*                                                                    */
  1088.  CheckAnsi: PROCEDURE
  1089.    thisRC = -1
  1090.  
  1091.    trace off
  1092.                          /* install a local error handler              */
  1093.    SIGNAL ON ERROR Name InitAnsiEnd
  1094.  
  1095.    "@ANSI 2>NUL | rxqueue 2>NUL"
  1096.  
  1097.    thisRC = 0
  1098.  
  1099.    do while queued() <> 0
  1100.      queueLine = lineIN( "QUEUE:" )
  1101.      if pos( " on.", queueLine ) <> 0 | ,                       /* USA */
  1102.         pos( " (ON).", queueLine ) <> 0 then                    /* GER */
  1103.        thisRC = 1
  1104.    end /* do while queued() <> 0 */
  1105.  
  1106.  InitAnsiEnd:
  1107.  signal off error
  1108.  RETURN thisRC
  1109.  
  1110.  
  1111.  
  1112.  
  1113. /*********************************/
  1114. /* PROCESS A TABLE */
  1115. DO_TABLE:PROCEDURE EXPOSE BODY TABLES. ignore_width tablemode2 tablemaxnest  charwidth linelen_orig ,
  1116. parse arg table1
  1117.  
  1118. drop tables.
  1119.  
  1120. tableinner=0
  1121. tables.0=1
  1122. tables.1.!rows=0
  1123. tables.1.1.!cols=0
  1124. tables.1.1.!totcols=0
  1125. tables.1.!errors=''
  1126. parse var table1 . tables.1.!spec
  1127.  
  1128. curtables=1
  1129.  
  1130. DO FOREVER
  1131.    if body='' then leave
  1132.    parse var body v1 '<' v2a '>' body
  1133.    v2=strip(translate(word(v2a,1)))
  1134.  
  1135.   tfoo=wordpos(v2,'TABLE TR TD TH /TABLE')
  1136.  
  1137.   if v2='TABLE' then do
  1138.       tableinner=tableinner+1
  1139.   end /* do */
  1140.  
  1141.   if tablemaxnest<tableinner  & tfoo>0 then do     /* inner tables not allowed, then..*/
  1142.       select
  1143.           when tablemode2=2 then do
  1144.              v2=strip(word('TL LI LI LI /TL',tfoo)) ;v2a=v2
  1145.           end
  1146.           when tablemode2=3 then do
  1147.              v2=strip(word('HR1 P BR BR HR2 ',tfoo)); v2a=v2
  1148.           end
  1149.           otherwise nop           /* make a table using ascii and/or lineart */
  1150.       end               /* select */
  1151.    end
  1152.    if tfoo=5 then tableinner=max(0,tableinner-1)
  1153.  
  1154.  
  1155.    if tfoo>0 then do    /*dump prior stuff, or perhaps convert */
  1156.            curtable=strip(word(curtables,1))
  1157.            currow=tables.curtable.!rows
  1158.            curcol=tables.curtable.currow.!cols
  1159.            if curcol>0 then do          /* add stuff */
  1160.               tables.curtable.currow.curcol.!stuff=tables.curtable.currow.curcol.!stuff||v1
  1161.            end
  1162.            else do
  1163.              if translate(v1,' ','0d0a0009'x)<>' ' then  say v1 ":ERROR:: Material outside of column at table " curtable " row " currow
  1164.            end /* do */
  1165.    end
  1166.  
  1167. /* TR: new row,  TD or TH: new colum, TABLE: new table definition */
  1168.    select
  1169.       when v2='TR' then do
  1170.         curtable=strip(word(curtables,1))
  1171.         currow=tables.curtable.!rows+1
  1172.         tables.curtable.!rows=currow
  1173.         parse var v2a . tables.curtable.currow.!spec
  1174.         tables.curtable.currow.!cols=0
  1175.         tables.curtable.currow.!totcols=0
  1176.  
  1177.       end /* do */
  1178.  
  1179.       when v2='TD' | v2='TH' then do
  1180.         curtable=strip(word(curtables,1))
  1181.         currow=tables.curtable.!rows
  1182.         curcol=tables.curtable.currow.!cols
  1183.  
  1184.         if currow=0 then do
  1185.                 tables.curtable.!rows=1
  1186.                 tables.curtable.1.!spec=''
  1187.                 tables.curtable.!errors=tables.curtable.!errors';MISSING_LEADING_TR'
  1188.                 currow=1
  1189.                 curcol=0
  1190.         end /* do */
  1191.  
  1192.         tdcols=get_elem_val(v2a,'COLSPAN')
  1193.         if datatype(tdcols)<>'NUM' then tdcols=1
  1194.         if tdcols<=0  then tdcols=1
  1195.         tdrows=get_elem_val(v2a,'ROWSPAN')
  1196.         if datatype(tdrows)<>'NUM' then tdrows=1
  1197.         if tdrows<=0 then tdrows=1
  1198.  
  1199.         curcol=curcol+1
  1200.         tables.curtable.currow.!cols=curcol
  1201.         tables.curtable.currow.!totcols=tables.curtable.currow.!totcols+tdcols
  1202.         parse var v2a . tables.curtable.currow.curcol.!spec
  1203.         tables.curtable.currow.curcol.!TH=v2
  1204.         tables.curtable.currow.curcol.!stuff=''
  1205.         tables.curtable.currow.curcol.!colspan=tdcols
  1206.         tables.curtable.currow.curcol.!rowspan=tdrows
  1207.       end /* do */
  1208.  
  1209.       when v2='TABLE' then do           /* a sub table */
  1210.  
  1211.         kurtable=strip(word(curtables,1))
  1212.         kurrow=tables.kurtable.!rows
  1213.         kurcol=tables.kurtable.kurrow.!cols
  1214.         curtable=tables.0+1
  1215.  
  1216.         if kurcol>0 then do          /* add stuff */
  1217.             moose= tables.kurtable.kurrow.kurcol.!stuff
  1218.             tables.kurtable.kurrow.kurcol.!stuff=moose||' <_TABLE_ 'curtable '>'
  1219.         end
  1220.         else do
  1221.            if translate(v1,' ','0d0a0009'x)<>' ' then do
  1222.                  say v1 ":ERROR:: NEW table of column at table " kurtable " row " kurrow
  1223.                 tables.kurtable.!errors=tables.kurtable.!errors';PREMATURE_NEW_COLUMN'
  1224.            end
  1225.         end /* do */
  1226.  
  1227.         TABLES.0=CURTABLE
  1228.         curtables=curtable' 'curtables
  1229.         tables.curtable.!rows=0
  1230.         tables.curtable.1.!cols=0
  1231.         tables.curtable.1.!totcols=0
  1232.         tables.curtable.!errors=''
  1233.         PARSE VAR V2A . TABLES.CURTABLE.!SPEC
  1234.  
  1235.       end /* do */
  1236.  
  1237.       when v2='/TABLE' then do                  /* end of table, pop an index from curtables */
  1238.            if words(curtables)=1 then leave
  1239.            parse var curtables . curtables
  1240.       end
  1241.  
  1242.       otherwise do              /* add to !stuff of current cell */
  1243.         curtable=strip(word(curtables,1))
  1244.  
  1245.          v2a2='<'v2a'>'
  1246.  
  1247.          currow=tables.curtable.!rows ; curcol=tables.curtable.currow.!cols
  1248.          if currow=0 | curcol=0 then do
  1249.                 say " ERROR: row or column not specified ("currow curcol")"
  1250.                 iterate
  1251.          end
  1252.          tables.curtable.currow.curcol.!stuff=tables.curtable.currow.curcol.!stuff||v1||v2a2
  1253.      end
  1254.   end                   /*select */
  1255. end
  1256.  
  1257.  
  1258. return 1
  1259.  
  1260.  
  1261.  
  1262. /************/
  1263. /* determine tablewidth in character s*/
  1264. get_tablewidth:procedure expose charwidth linelen_orig
  1265. parse arg specs,linelen
  1266.  
  1267. tablewidth=strip(get_elem_val(specs,'WIDTH'))
  1268.  
  1269. if tablewidth='' then  do
  1270.   tablewidth=linelen
  1271. end
  1272. else do
  1273.    if right(tablewidth,1)='%' then do           /* pct of line lenght */
  1274.          tablewidth=strip(tablewidth,,'%')
  1275.          if datatype(tablewidth)<>'NUM' then do
  1276.             tablewidth=linelen
  1277.          end
  1278.          else do
  1279.             tablewidth=(tablewidth/100)*linelen_orig
  1280.             tablewidth=trunc(min(tablewidth,linelen))
  1281.          end
  1282.    end /* do */
  1283.    else do              /* convert pixels to charactes */
  1284.          if datatype(tablewidth)='NUM' then do
  1285.             tablewidth=trunc(min(tablewidth/charwidth,linelen))
  1286.          end /* do */
  1287.          else do
  1288.             tablewidth=linelen
  1289.          end
  1290.    end /* do */
  1291.    tablewidth=max(2,tablewidth)   /* can't bee too small */
  1292. end /* do */
  1293. return tablewidth
  1294.  
  1295. /****************/
  1296. /* determine max width of cell (check for WIDTH element */
  1297. get_tdwidth:procedure expose charwidth 
  1298. parse arg aspec,linelen,ign,stuff2,colspan
  1299.  
  1300. if ign<>1 then tdwidth=strip(get_elem_val(aspec,'WIDTH'))
  1301.  
  1302.  
  1303. if tdwidth='' | ign=1 then  do
  1304.   if ign=2 | colspan>1  then return '0 0 '
  1305.   eff=qcell_width(stuff2,linelen)                /* rough guess as to max linelength */
  1306.   return 0' 'eff      /* 0 means "no default length found */
  1307. end
  1308.  
  1309. /* convert % to characters */
  1310. if right(tdwidth,1)='%' then do
  1311.          tdwidth=strip(tablewidth,,'%')
  1312.          if datatype(tdwidth)<>'NUM' then  return 0  /* error- ignore width */
  1313.          tdwidth=trunc(min(linelen*tdwidth/100,linelen))
  1314. end /* do */
  1315. else do              /* convert pixels to charactes */
  1316.       if datatype(tdwidth)<>'NUM' then  return 0  /* error- ignore width */
  1317.       tdwidth=min(trunc(tdwidth/charwidth,linelen))
  1318. end /* do */
  1319. return trunc(max(tdwidth,1))
  1320.  
  1321.  
  1322.  
  1323. /*************************/
  1324. /* quick guess at length of line in a cell (after html mappings */
  1325. qcell_width:procedure
  1326. parse arg stuff,deflen
  1327. ithl=0
  1328. aline=''
  1329. do forever
  1330.  
  1331.   if stuff='' then do
  1332.         ithl=ithl+1 ; tlines.ithl=aline
  1333.         leave
  1334.   end /* do */
  1335.  
  1336.   parse upper var stuff t1 '<' t2 '>' stuff
  1337.  
  1338.   t1=space(translate(t1,' ','000d0a0d'x))
  1339.   aline=aline||t1
  1340.  
  1341.   parse var t2 t2a t2b ; t2a=strip(t2a); t2a=strip(t2a,,'/')
  1342.  
  1343.  
  1344.   if wordpos(t2a,'HR HR2 HR1 P BR H1 H2 H3 H4 H5 H6 H7 PRE ')>0 then do
  1345.         ithl=ithl+1 ; tlines.ithl=alineadd||aline
  1346.         aline='' ; iterate ; alineadd=''
  1347.   end
  1348.  
  1349.   if t2a='_TABLE_' then do
  1350.         ithl=ithl+1 ; tlines.ithl=copies('x',deflen); aline='' ;alineadd=''
  1351.         iterate
  1352.   end /* do */
  1353.  
  1354.   if wordpos(t2a,'BLOCKQUOTE TL SELECT UL DL OL MENU DIR ')>0 then do
  1355.         ithl=ithl+1 ; tlines.ithl=alineadd||aline
  1356.         alineadd='         ' ; iterate                /* no nested indenting, might fix later */
  1357.    end        
  1358.  
  1359.    if t2a='INPUT' then do
  1360.           atype=TRANSLATE(get_elem_val(t2,'TYPE'))
  1361.           IF ATYPE='' then ATYPE='TEXT'
  1362.           avalue=get_elem_val(t2,'VALUE',1)
  1363.           if atype='RADIO' | atype='CHECKBOX' then do
  1364.             aline=aline' '
  1365.           end
  1366.           if atype='TEXT' then do
  1367.                av2=get_elem_val(t2,'SIZE')
  1368.                if av2='' then av2=get_elem_val(t2a,'MAXLENGTH')
  1369.                if av2='' then av2=4
  1370.                aline=aline'  '||copies(' ',av2)
  1371.           end
  1372.           if atype='SUBMIT' | atype='RESET' then do
  1373.                 if avalue='' then avalue='     '
  1374.                 aline=aline'  '||avalue
  1375.           end /* do */
  1376.          iterate
  1377.    end
  1378.  
  1379. /* paragraph modifiers */
  1380.    if wordpos(t2a,'A OPTION '||doquote)>1 then do
  1381.         aline=aline' '                  /* add space for quote characters */
  1382.    end /* do */
  1383.  
  1384. end
  1385.  
  1386. mxlen=0
  1387. do iii=1 to ithl
  1388.     mxlen=max(mxlen,length(tlines.iii))
  1389. end
  1390.  
  1391. drop tlines.
  1392.  
  1393. return max(2,mxlen)
  1394.  
  1395.  
  1396.  
  1397.  
  1398.  
  1399. /******************************/
  1400. /* various utility procedures */
  1401.  
  1402. /***********************************/
  1403. /* load libraries, set ansi, set defaults */
  1404. loadlibs:
  1405. foo=rxfuncquery('sysloadfuncs')
  1406. if foo=1 then do
  1407.   foo2=RxFuncAdd('SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs')
  1408.   if foo2=0 then call SysLoadFuncs
  1409. end
  1410.  
  1411. cy_ye=' '; normal=''; bold='';re_wh='';reverse='';aesc=''
  1412. if noansi<>1 then do
  1413.   aesc='1B'x
  1414.   cy_ye=aesc||'[37;46;m'
  1415.   normal=aesc||'[0;m'
  1416.   bold=aesc||'[1;m'
  1417.   re_wh=aesc||'[31;47;m'
  1418.   reverse=aesc||'[7;m'
  1419. end
  1420.  
  1421. return 1
  1422.  
  1423.  
  1424. /********************/
  1425. /* get, possibly quoted, value of a field in an html type <element > */
  1426. get_elem_val:procedure
  1427. parse arg haystack,needle,lc
  1428.  
  1429. thay=' 'translate(haystack)
  1430. needle=' '||translate(needle)||'='
  1431.  
  1432. foo=pos(needle,thay)
  1433. if foo=0 then return ''
  1434. haystack=strip(substr(haystack,foo+length(needle)-1))
  1435.  
  1436. if abbrev(haystack,'"')=1 then
  1437.   parse var haystack '"' aval '"' .
  1438. else
  1439.   parse var haystack aval .
  1440.  
  1441. if lc<>1 then aval=translate(aval)
  1442. return aval
  1443.  
  1444.  
  1445. /***************/
  1446. /* convert to ascii, but only if >1 character that is
  1447.  a numeric value. */
  1448. do_d2c:procedure expose lineart
  1449. parse arg a1,defval,islist
  1450.  
  1451.  
  1452. if islist=1 then do
  1453.   alist2=''
  1454.   do forever
  1455.      if a1='' then leave
  1456.      parse var a1 a1a a1 ; a1a=strip(a1a)
  1457.      if length(a1a)>1 & datatype(a1a)='NUM' then do
  1458.        if lineart>-1 then
  1459.          a1a=d2c(a1a)
  1460.        else
  1461.          a1a=defval
  1462.      end
  1463.      alist2=alist2||a1a' '
  1464.   end /* do */
  1465.   return alist2
  1466. end /* do */
  1467. else do
  1468.   if length(a1)>1 & datatype(a1)='NUM' then  do
  1469.     if lineart>-1 then
  1470.        a1=d2c(a1)
  1471.     else
  1472.        a1=defval
  1473.   end
  1474.   return a1
  1475. end
  1476.  
  1477.  
  1478.  
  1479. /* -------------------- */
  1480. /* get a yes or no , return 1 if yes */
  1481. yesno:procedure expose normal reverse bold
  1482. parse arg fooa , allopt,altans
  1483. if altans<>" " & words(altans)>1 then do
  1484.    w1=strip(word(altans,1))
  1485.    w2=strip(word(altans,2))
  1486.    a1=left(w1,1) ; a2=left(w2,1)
  1487.    a1a=substr(w1,2) ; a2a=substr(w2,2)
  1488. end
  1489. else do
  1490.     a1='Y' ; a1a='es'
  1491.     a2='N' ; a2a='o'
  1492. end  /* Do */
  1493. ayn='  '||bold||a1||normal||a1a||'\'||bold||a2||normal||a2a
  1494. if allopt=1 then  ayn=ayn||'\'||bold||'A'||normal||'ll'
  1495.  
  1496. do forever
  1497.  foo1=normal||reverse||fooa||normal||ayn
  1498.  call charout,  foo1 normal ':'
  1499.  pull anans
  1500.  if abbrev(anans,a1)=1 then return 1
  1501.  if abbrev(anans,a2)=1 then return 0
  1502.  if allopt=1 & abbrev(anans,'A')=1 then return 2
  1503. end
  1504.  
  1505.  
  1506.  
  1507. /*********************/
  1508. /* select nth from a sequence of words -- use first if nth ># words */
  1509. nth_word:procedure
  1510. parse arg alist,nth
  1511. if words(alist)=1 then return alist
  1512. if nth>words(alist) then nth=1
  1513. return strip(word(alist,nth))
  1514.  
  1515. /************/
  1516. /* running status report to screen  */
  1517. noteit:procedure
  1518. parse arg nowlen,waslen,blocksize,prenote
  1519.  
  1520. if nowlen-waslen> blocksize then do
  1521.    call charout,'0d'x || '0d'x||prenote' 'nowlen
  1522.    return nowlen
  1523. end /* do */
  1524. return waslen
  1525.  
  1526.  
  1527. /***********************/
  1528. /* wrap or trip a string */
  1529. fix_linelen:procedure
  1530. parse arg aline,llen,itype,adash
  1531. crlf='0d0a'x
  1532.  
  1533. if adash='' then adash=' '
  1534. if length(aline)<=llen then return aline
  1535. if itype=-1 then return left(aline,llen)  /* trim */
  1536. if itype=0 then do
  1537.   bud=''
  1538.   do mm=1 to length(aline) by (llen-1)
  1539.      bud=bud||substr(aline,mm,llen-1)||adash||crlf
  1540.   end /* do */
  1541.   bud=left(bud,length(bud)-3)   /* clip last adash crlf */
  1542.   return bud
  1543. end
  1544. return aline            /* as is */
  1545.  
  1546.  
  1547.  
  1548. /***************/
  1549. /* ADD SPECIAL "LOGICAL ELEMENT" CHARACTERS? */
  1550. fix_quote_anchor:procedure expose anchoron1 anchoron2 quoteon1 quoteon2 ,
  1551.                 quotestring1 quotestring2 prea posta thispara
  1552. parse arg t1
  1553.  
  1554.      firstspace=verify(t1,' ')
  1555.      if firstspace=0 then signal stp2
  1556.  
  1557.      if anchoron1=1 then do
  1558.           t1=insert(prea,t1,firstspace-1)     /* preface this with prea */
  1559.           anchoron1=0
  1560.      end
  1561.  
  1562.      if quoteon1=1 then do
  1563.            t1=insert(quotestring1,t1,firstspace-1)
  1564.            quoteon1=0
  1565.      end
  1566.  
  1567. stp2:
  1568.      lenth=length(thispara)
  1569.      if thispara='' then
  1570.          lastchar=0
  1571.      else
  1572.          lastchar= 1+lenth-verify(reverse(thispara),' ')
  1573.  
  1574.      if anchoron2=1 then do
  1575.             thispara=insert(posta,thispara,lastchar)
  1576.             anchoron2=0
  1577.      end
  1578.      if quoteon2=1 then do
  1579.            thispara=insert(quotestring2,thispara,lastchar)
  1580.            quoteon2=0
  1581.      end
  1582.      return t1
  1583.  
  1584.  
  1585. /**********************/
  1586. /* convert table elements? (uses globals */
  1587. cvt_table_elements:procedure expose t2a tablemode 
  1588. parse arg t2,inmain
  1589.  
  1590.     tfoo=wordpos(t2,'TABLE TR TD TH /TABLE ')
  1591.     if tfoo>0 then do           /* a table element ... */
  1592.  
  1593. /*   note: if tablemode=1, one should NEVER see TR TD or TH */
  1594.       if tablemode=1 & tfoo>1 & inmain=1 then do
  1595.           say ' '
  1596.           say "Warning: syntax error; TD TR or TH detected in main "
  1597.       end /* do */
  1598.  
  1599.       select
  1600.           when tablemode=2 then do
  1601.              t2=strip(word('TL LI LI LI /TL',tfoo)) ;t2a=t2
  1602.           end
  1603.           when tablemode=3 then do
  1604.              t2=strip(word('HR1 P BR BR HR2 ',tfoo)); t2a=t2
  1605.           end
  1606.           otherwise nop           /* make a table using ascii and/or lineart */
  1607.       end               /* select */
  1608.    end          /* tfoo */
  1609.    return t2
  1610.  
  1611.  
  1612. /*************/
  1613. /* CONVERT &ENCODING */
  1614. CONVERT_CODES:PROCEDURE
  1615. PARSE ARG T1,CAPON,ISPRE,ULINEON,ISTH
  1616.  
  1617. IF T1='' then RETURN T1
  1618.  
  1619.       if capon>0 | ISTH='TH' then t1=translate(t1)
  1620.       if ispre=0 then t1=translate(T1,' ','0d0a0009'x)
  1621.       if ulineon=1 then do
  1622.            if ispre=0 then
  1623.               t1= translate(space(t1,1),'_',' ')
  1624.            else
  1625.               t1=translate(t1,'_',' ')
  1626.       end /* do */
  1627.  
  1628.       tt1=t1 ;t1=''
  1629.       do forever
  1630.         if tt1='' then leave
  1631.         parse var tt1 v1 '&' v2a tt1
  1632.  
  1633.         t1=t1||v1
  1634.         goo=pos(';',v2a)
  1635.  
  1636.         if goo>0 then do
  1637.             v2=left(v2a,goo-1)
  1638.             v3a=substr(v2a,goo+1)
  1639.             tt1=v3a' 'tt1
  1640.         end /* do */
  1641.         else do
  1642.            v2=v2a
  1643.         end /* do */
  1644.  
  1645.         v2=strip(v2)
  1646.  
  1647.         if v2<>"" then do
  1648.             v2=strip(translate(v2))
  1649.             v2=strip(v2,,'#')
  1650.             select
  1651.                when v2='AMP' then t1=t1||'&'
  1652.                when v2='LT' then t1=t1||'<'
  1653.                when v2='GT' then t1=t1||'>'
  1654.                when v2='QUOT' then t1=t1||'"'
  1655.                when v2='NBSP' then t1=t1||'01'x
  1656.                when datatype(v2)='NUM' then t1=t1||d2c(v2)
  1657.                otherwise t1=t1||' 'translate(v2)' '
  1658.             end  /* select */
  1659.         end /* v2<>"" */
  1660.       end /* FOREVER  */
  1661. RETURN T1
  1662.  
  1663.  
  1664.  
  1665.  
  1666. /***********************/
  1667. /* a lineout with a fix for regina rexx */
  1668. lineout2:
  1669. parse arg oofile,dothis1
  1670. dothis2=dothis1  ; leaveit=0
  1671. do until leaveit=1
  1672.    ffo=pos('0d0a'x,dothis2)
  1673.    if ffo=0 then do
  1674.      ooline=dothis2 ; leaveit=1    /* end */
  1675.    end
  1676.    else do
  1677.       if ffo=1 then do  /* empty line */
  1678.           ooline='  '
  1679.           dothis2=substr(dothis2,3)
  1680.       end
  1681.       else do
  1682.           ooline=left(dothis2,ffo-1)
  1683.           dothis2=substr(dothis2,ffo+2)
  1684.       end
  1685.     end
  1686.     call lineout oofile,ooline
  1687. end /* do */
  1688. return 1
  1689.  
  1690.  
  1691. /* END OF UTILITY PROCS */
  1692. /******************/
  1693.  
  1694.  
  1695.  
  1696. /*******************************************/
  1697. /* GENERATE A TABLE INTO A TEMP VARIABLE */
  1698. GEN_TABLE:PROCEDURE EXPOSE TABLES. outfile ,
  1699.        pretitle posttitle prea posta preh1 posth1 prehn posthn imgstring preimg postimg ,
  1700.        docaps douline doquote quotestring1 quotestring2 hn_outline hn_Numbers. ol_numbers ,
  1701.        flagmenu flagul flagselect flagselect2 radiobox checkboxk  errorflag display_errors ,
  1702.        tablevert tablehoriz tablefiller lineart submitmark1 submitmark2 ,
  1703.        textmark1 textmark2 textmark radioboxcheck checkboxcheck toolongword hrbig ,
  1704.        tablemode2 flagtl  tableborder showallopts suppress_empty_table charwidth ,
  1705.        linelen_orig wasblank suppress_blanklines ignore_width
  1706.  
  1707.  
  1708. crlf='0d0a'x
  1709. arow.0=0
  1710.  
  1711. PARSE ARG nth,linelen
  1712.  
  1713. l0=linelen
  1714.  
  1715. /* see if WIDTH attribute for this table */
  1716. if ignore_width<>1 then do
  1717.    linelen=get_tablewidth(tables.nth.!spec,linelen)  /* might be less then linelen */
  1718. end
  1719.  
  1720. call get_border_info    /* get border character info (uses only globals, and sets BVAL  */
  1721.  
  1722.  
  1723. /* determine max columns in table, and WIDTH info of cells */
  1724. ccols=1; CSCOLS=1
  1725. do iii=1 to tables.nth.!rows
  1726.   cScols=max(ccols,tables.nth.iii.!totcols)
  1727.   ccols=max(ccols,tables.nth.iii.!cols)
  1728.   do jcc=1 to tables.nth.iii.!cols
  1729.        gogo=get_tdwidth(tables.nth.iii.jcc.!spec,linelen,ignore_width,tables.nth.iii.jcc.!stuff, ,
  1730.                         tables.nth.iii.jcc.!colspan)
  1731.        parse var gogo gogo1 gogo2
  1732.        if gogo2='' then gogo2=0
  1733.        tables.nth.iii.jcc.!tdwidth=gogo1
  1734.        tables.nth.iii.jcc.!mxll=min(gogo2,trunc(1.5*l0))
  1735.  
  1736.    end
  1737. end /* do */
  1738.  
  1739. /* determine width of each column, given WIDTH info exists from above */
  1740. do kk=1 to cscols
  1741.    colwidths.kk=0               /* 0 signfies "unspecified */
  1742.    colwidths2.kk=0              /* unwrapped line lengths (concatended */
  1743. end /* do */
  1744. do kr =1 to tables.nth.!rows
  1745.      kc2=1
  1746.      do kc=1 to tables.nth.kr.!cols
  1747.           cspan=tables.nth.kr.kc.!colspan
  1748.           cwidth=tables.nth.kr.kc.!tdwidth
  1749.           colwidths.kc2=max(colwidths.kc2,cwidth)
  1750.           if cwidth=0 then do
  1751.              colwidths2.kc2=max(colwidths2.kc2,tables.nth.kr.kc.!mxll)
  1752.           end /* do */
  1753.           kc2=kc2+cspan
  1754.      end /* do */
  1755. end /* do */
  1756.  
  1757. /* colwidths2.0 ... */
  1758. colwidths2.0=0
  1759. do kk=1 to cscols
  1760.   colwidths2.0=colwidths2.0+colwidths2.kk
  1761. end /* do */
  1762.  
  1763. /* determine missing widths */
  1764.  
  1765. /* first, assign widths to columns with no width specified  -- use  td specific ".!maxlinelen" info*/
  1766. nsum=0 ; nnone=0
  1767. do kk=1 to cscols
  1768.    nsum=nsum+colwidths.kk
  1769.    if colwidths.kk=0 then do
  1770.       nnone=nnone+1   
  1771.     end
  1772. end /* do */
  1773. /* 2) add missings? */
  1774. if nnone>0 then do
  1775.    misslen=linelen-nsum    /* default width to use for non width specfied columns */
  1776.    deflen=trunc(misslen/nnone)
  1777.  
  1778.    nsum=0
  1779.    do kk=1 to cscols
  1780.        if colwidths.kk=0 then do
  1781.            if colwidths2.kk=0 then do
  1782.                colwidths.kk=deflen
  1783.            end
  1784.            else do
  1785.               t1=colwidths2.kk/colwidths2.0
  1786.               colwidths.kk=max(2,trunc(t1*misslen))
  1787.            end
  1788.        end
  1789.        nsum=nsum+colwidths.kk
  1790.    end
  1791. end
  1792.  
  1793. /* normalize (insure sum equals linelen) */
  1794. if nsum<>linelen then do 
  1795.    afact=linelen/nsum
  1796.    nsum=0
  1797.    do kk=1 to cscols
  1798.         colwidths.kk=trunc(colwidths.kk*afact)
  1799.         nsum=nsum+colwidths.kk
  1800.    end /* do */
  1801.    colwidths.1=colwidths.1+linelen-nsum           /* truncations get added to first column */
  1802. end /* do */
  1803.  
  1804. if bval<>0 then colwidths.1=colwidths.1-1                       /* leave room for left side border */
  1805.  
  1806. mincellwidth=linelen            /* used for a warning message */
  1807. funk=''
  1808. do kk=1 to cscols
  1809.    mincellwidth=min(mincellwidth,colwidths.kk)
  1810.    funk=funk' 'colwidths.kk
  1811. end /* do */
  1812.  
  1813. /* compute actual size of cells in each row, taking colspan into account */
  1814. /* also, add filler cell if need be */
  1815. do kr=1 to tables.nth.!rows
  1816.     jc1=1 ; mycols=tables.nth.kr.!cols
  1817.     do kc=1 to mycols
  1818.        actsize=-1
  1819.        jc2=jc1+tables.nth.kr.kc.!colspan
  1820.        do jj=jc1 to (jc2-1)
  1821.           actsize=actsize+colwidths.jj
  1822.        end /* do */
  1823.        tables.nth.kr.kc.!linecc=actsize
  1824.        jc1=jc2
  1825.     end /* do */
  1826.     if jc2<=cscols then do
  1827.           toadd=-1
  1828.           if bval>0 then toadd=-2
  1829.           do jj=jc2 to cscols
  1830.              toadd=toadd+colwidths.jj+1
  1831.           end /* do */
  1832.           mycols=mycols+1
  1833.           tables.nth.kr.!filler=copies(tablefiller,toadd)     /* FILLER FOR AN EMPTY CELL */
  1834.                                 /* implicitly, if mycols<cscols, this will be checked */
  1835.     end /* do */
  1836. end /* do */
  1837.  
  1838. call go_make_bars               /* make horizontal diviers (use/set globals */
  1839.  
  1840. IF mincellwidth<14  then  do
  1841.     tables.nth.!errors=tables.nth.!errors||"NARROW_CELLS"
  1842.     TABLEMODE=3         /* use HR BR instead for internal tables */
  1843. end
  1844. else do
  1845.   tablemode=tablemode2            /* tablemode for nested tables */
  1846. end
  1847. wasblank=0
  1848. indent=0; rightindent=0
  1849. ispre=0                 /* <PRE> is on? */
  1850. olcnts=''                 /* OL count */
  1851. lastelem=''
  1852. capon=0
  1853. ulineon=0
  1854. listtypes=''
  1855. anchoron=0 ; anchoron1=0; anchoron2=0
  1856. quoteon=0 ; quoteon1=0 ; quoteon2=0
  1857. ddon=1
  1858. thispara=''             /* current paragraph */
  1859. iscenter=0
  1860.  
  1861. if hn_outline>0 then do
  1862.   do jj=hn_outline to 7
  1863.      hn_outlines.jj=0
  1864.   end /* do */
  1865. end
  1866.  
  1867. sendout_internal=1
  1868. sendout_var=''
  1869.  
  1870. datable=horizbar1||crlf               /* top line of da table */
  1871. tablealive=0                    /* used to suppress empty table */
  1872.  
  1873. do Jir=1 to tables.nth.!rows
  1874.  
  1875. ic0=1
  1876. do ic=1 to tables.nth.Jir.!cols
  1877.  
  1878.  body=tables.nth.Jir.ic.!stuff
  1879.  
  1880.  linecc=tables.nth.jir.ic.!linecc
  1881.  if ic=tables.nth.jir.!cols & bval=0 then linecc=linecc+1
  1882.  
  1883.  indent=0 ; rightindent=0
  1884.  
  1885.  do forever
  1886.     if body='' then leave
  1887.  
  1888.     parse var body t1 '<' t2a '>' body
  1889.  
  1890. /* add t1 to thispara */
  1891.  
  1892. /* convert &codes */
  1893.      T1=CONVERT_CODES(T1,CAPON,ISPRE,ULINEON,TABLES.NTH.JIR.IC.!TH)
  1894.  
  1895.      t1=fix_quote_anchor(t1)  /* may change globals */
  1896.  
  1897. /* add more content ..... */
  1898.      thispara=thispara||t1      /* ADD T1 TO THISPARA FOR EVENTUAL OUTPUT */
  1899.  
  1900. /* now, process the <element> */
  1901.     t2=strip(translate(word(t2a,1)))             /* get rid of element modifiers */
  1902.     if left(t2,1)='/'  then
  1903.         t2end=substr(t2,2)
  1904.     else
  1905.         t2end=''
  1906.  
  1907. /* convert table elements? */
  1908.     t2=cvt_table_elements(t2)
  1909.  
  1910.  
  1911. /* THIS DOES THE WORK */
  1912.      if t2='_TABLE_' then do            /* this is an internal table -- recurse! */
  1913.            parse var t2a . newtable ; newtable=strip(newtable)
  1914.            foo=sendout(thispara,ispre,indent,aflag,lineCC)
  1915.            aflag='' ;THISPARA=''
  1916.            if  datatype(newtable)='NUM' then do
  1917.               newtable=strip(newtable)
  1918.               thispara=gen_table(newtable,linecc)
  1919.               foo=sendout(thispara,1,indent,'',lineCC)
  1920.               if tables.newtable.!errors<>' ' then
  1921.                  tables.1.!errors=tables.1.!errors||';'NEWTABLE':'tables.newtable.!errors
  1922.               thispara='' ;aflag=''
  1923.            end
  1924.      end /* do */
  1925.      else do
  1926.         call interpret_elems linecc /* generic interprets */
  1927.      end
  1928.   end           /* body forever */
  1929.  
  1930. /* all done with this cell -- write it out */
  1931.   foo=sendout(thispara,ispre,indent,aflag,lineCC)
  1932.   thispara=''
  1933.  
  1934.   nlines=0
  1935.   do forever
  1936.      if sendout_var='' then leave
  1937.      nlines=nlines+1
  1938.      parse var sendout_var arow.ic.nlines (crlf) sendout_var
  1939.   end /* do */
  1940.   arow.ic.0=nlines
  1941.   sendout_var=''
  1942.   arow.0=max(arow.0,nlines)
  1943.  
  1944.  
  1945. end    /* ic */
  1946.  
  1947. /* done with all cells in this row of the table.
  1948.   horiz cappend each line of each cell to create linelen lines,
  1949.   vert appen these lines to make a row of cells */
  1950.  
  1951. /* type of alighment */
  1952. rspec=tables.nth.Jir.!spec
  1953. dalign=get_elem_val(rspec,'ALIGN')
  1954. dalignv=get_elem_val(rspec,'ALIGNV')
  1955.  
  1956. thisrows="" ; tralive=0      /* assume empty row */
  1957. do iii0=1 to arow.0              /* max number of lines */
  1958.   thisline=''
  1959.  
  1960.   do ic=1 to tables.nth.Jir.!cols
  1961.       linecc=tables.nth.jir.ic.!linecc
  1962.  
  1963.       if iii0=1 then do          /* cell specs , check on first line */
  1964.          calign=''; calignv=''
  1965.          cspec=tables.nth.Jir.ic.!spec
  1966.          calignv=get_elem_val(cspec,'VALIGN')
  1967.            if calignv="" then calignv=dalignv
  1968.          calign=get_elem_val(cspec,'ALIGN')
  1969.            if calign="" then calign=dalign
  1970.          calign.ic=calign
  1971.          lineoffset.ic=0
  1972.          if calignv='MIDDLE' | calignv='CENTER' | calignv='' then do
  1973.             lineoffset.ic=trunc((arow.0-arow.ic.0)/2)
  1974.          end /* do */
  1975.       end
  1976.       iii=iii0-lineoffset.ic
  1977.  
  1978.       if iii<1 | iii>arow.ic.0 then do       /* fller line ?*/
  1979.          lcc=linecc
  1980.          if datatype(lcc)<>'NUM' then lcc=l0
  1981.          lcc=max(lcc,1)
  1982.          addme=copies(tablefiller,lcc)
  1983.       end
  1984.       else do                   /* got a line to add */
  1985.         addme0=arow.ic.iii
  1986.         if addme0<>' ' then do
  1987.             tralive=1  ;tablealive=1
  1988.         end /* do */
  1989.         select
  1990.            when calign.ic='MIDDLE' | calign.ic='CENTER' then
  1991.               addme=center(addme0,linecc)
  1992.            when calign.ic='RIGHT' then
  1993.               addme=right(addme0,linecc)
  1994.            otherwise
  1995.               addme=left(addme0,linecc,' ')
  1996.         end  /* select */
  1997.       end               /* non filler line */
  1998.       if bval=0 & ic=1 then
  1999.          thisline=addme
  2000.       else
  2001.          thisline=thisline||TVERT||addme
  2002.  
  2003.  
  2004.   end /* do */
  2005.  
  2006. /* in case of insufficient cells .. */
  2007.   if cScols>tables.nth.Jir.!TOTcols then do
  2008.       thisline=thisline||tvert||tables.nth.jir.!filler
  2009.   end /* do */
  2010.  
  2011.   if bval<>0 then thisline=thisline||TVERT          /* END OF A LINE */
  2012.   thisrows=thisrows||thisline||CRLF     /* APPEND TO "LINES IN THIS ROW OF CELLS */
  2013.  
  2014. end             /* iii */
  2015.  
  2016.  
  2017. if tralive=0 & suppress_empty_table=1 then do  /* suppress empty row? */
  2018.      nop
  2019. end /* do */
  2020. else do
  2021.   if Jir<>tables.nth.!rows then
  2022.      datable=DATABLE||thisrows||horizbarm||CRLF
  2023.   else
  2024.      datable=DATABLE||thisrows||horizbar2||CRLF
  2025. end
  2026.  
  2027. arow.0=0
  2028.  
  2029. end             /* Jir */
  2030.  
  2031. sendout_internal=0
  2032.  
  2033. if tablealive=0 & suppress_empty_table=1 then return ' '
  2034.  
  2035. return datable
  2036.  
  2037.  
  2038.  
  2039. /***********************/
  2040. go_make_bars:
  2041.  
  2042. horizbar=copies(THORIZ,linelen-1)  /* TABLE WIDE DIVIDER LINE */
  2043. horizbar2=horizbar; horizbar1=horizbar ; horizbarm=horizbar
  2044.  
  2045. if lineart=1 & bval<>0 then do             /* ascii art? */
  2046.   horizbar1=d2c(218)
  2047.   horizbar2=d2c(192)
  2048.   horizbarm=d2c(195)
  2049.   do kk=1 to cScols
  2050.      horizbarm=horizbarm||copies(thoriz,colwidths.kk-1)
  2051.      horizbar1=horizbar1||copies(thoriz,colwidths.kk-1)
  2052.      horizbar2=horizbar2||copies(thoriz,colwidths.kk-1)
  2053.      if kk<>cScols then do
  2054.         horizbarm=horizbarm||d2c(197)
  2055.         horizbar1=horizbar1||d2c(194)
  2056.         horizbar2=horizbar2||d2c(193)
  2057.      end
  2058.   end
  2059.   horizbarm=horizbarm||d2c(180)
  2060.   horizbar1=horizbar1||d2c(191)
  2061.   horizbar2=horizbar2||d2c(217)
  2062.  
  2063. end
  2064.  
  2065. return 1
  2066.  
  2067.  
  2068. /***************************/
  2069. /* get border info */
  2070. get_border_info:
  2071.  
  2072. /* Border for this table */
  2073. SPECS=TABLES.NTH.!SPEC
  2074. bval=get_elem_val(specs,'BORDER')
  2075. if datatype(bval)<>'NUM' then bval=tableborder
  2076.  
  2077. if tableborder>1 then bval=trunc(tableborder)  /* force borders? */
  2078.  
  2079. IF  bval=0 then DO               /* border type */
  2080.    TVERT=' '; THORIZ=' '
  2081. end /* do */
  2082. else DO                 /* line art, or explicit character */
  2083.   if lineart<>1 then do
  2084.       tvert=tablevert
  2085.   end
  2086.   else do
  2087.      if bval=1  then
  2088.        tvert=d2c(179)
  2089.      else
  2090.         tvert=d2c(186)
  2091.   end
  2092.   if lineart<>1 then do
  2093.       thoriz=tablehoriz
  2094.   end
  2095.   else do
  2096.     if bval=1  then
  2097.       thoriz=d2c(196)
  2098.     else
  2099.       thoriz=d2c(205)
  2100.   end
  2101. END
  2102.  
  2103. return 1
  2104.  
  2105.  
  2106. /*********************/
  2107. /* routine to interpret html elements -- uses lots of globals */
  2108. interpret_elems:
  2109.  
  2110. parse arg Xlinelen
  2111. indent3=3
  2112. if xlinelen<22 then indent3=1
  2113.  
  2114. mindent3=3
  2115. if xlinelen<22 then mindent3=1
  2116.  
  2117. /* break off piece of body  */
  2118.  
  2119. /* look for line breakers */
  2120.     select
  2121.       when t2='HR' then do
  2122.  
  2123.          hrsize=get_elem_val(t2a,'SIZE')                /* line height */
  2124.          if datatype(hrsize)<>'NUM' then hrsize=1
  2125.          if hrsize<3 then
  2126.             hrchar='_'
  2127.          else
  2128.             hrchar=hrbig
  2129.  
  2130.          hrwidth=strip(get_elem_val(t2a,'WIDTH'))   /* line width */
  2131.          select
  2132.              when hrwidth='' then hrwidth=1.0
  2133.              when right(hrwidth,1)='%' then do
  2134.                  parse var hrwidth hrwidth '%' .
  2135.                  if datatype(hrwidth)='NUM' then
  2136.                     hrwidth=min(100,hrwidth)/100
  2137.                  else
  2138.                     hrwidth=1
  2139.              end /* do */
  2140.              otherwise do
  2141.                 if datatype(hrwidth)='NUM' then
  2142.                       hrwidth=min(1,hrwidth/640)
  2143.                 else
  2144.                        hrwidth=1
  2145.              end
  2146.          end
  2147.          hrchars=max(2,trunc((xlinelen-4)*hrwidth))
  2148.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2149.          call sendout ' '
  2150.          thispara='';aflag=0
  2151.          foo=sendout(center(copies(hrchar,hrchars),xlinelen),1,,,xlinelen)
  2152.          if hrsize>10 then
  2153.             foo=sendout(center(copies(hrchar,hrchars),xlinelen),1,,,xlinelen)
  2154.          call sendout ' '
  2155.  
  2156.       end
  2157.  
  2158.       when t2='HR1' then do
  2159.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2160.          thispara='';aflag=0
  2161.          if lineart>=0 then do
  2162.              foo=sendout(center(d2c(201)||copies(d2c(205),Xlinelen-6)||d2c(187),Xlinelen),1,,,xlinelen)
  2163.          end
  2164.          else do
  2165.              foo=sendout(center('/'copies('=',Xlinelen-6)'\',Xlinelen),1,,,xlinelen)
  2166.          end
  2167.          indent=indent+indent3
  2168.       end
  2169.  
  2170.       when t2='HR2' then do
  2171.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2172.          thispara='';aflag=0
  2173.          att='='
  2174.          if lineart>=0 then do
  2175.              foo=sendout(center(d2c(200)||copies(d2c(205),Xlinelen-6)||d2c(188),Xlinelen),1,,,xlinelen)
  2176.          end
  2177.          else do
  2178.              foo=sendout(center('\'copies('=',Xlinelen-6)'/',Xlinelen),1,,,xlinelen)
  2179.          end
  2180.          indent=max(indent-mindent3,0)
  2181.       end
  2182.  
  2183. /* H1 H2 H3 ... HEADERS */
  2184.       when wordpos(t2,'H1 H2 H3 H4 H5 H6 H7')>0 then do
  2185.          HN_LEVEL=WORDPOS(T2,'H1 H2 H3 H4 H5 H6 H7')
  2186.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2187.          thispara=''
  2188.          ah=getelem('/H')
  2189.          ah=remove_htmls(ah)
  2190.  
  2191.          docenter=0     /* don't add pre Hn stuff if centered */
  2192.  
  2193. /* Add an "outline" number */
  2194.         if hn_outline<=hn_level & hn_outline<>0 then do
  2195.            hn_outlines.hn_level=hn_outlines.hn_level+1
  2196.  
  2197.            do mmh=hn_outline to (hn_level-1)        /* fix up lower levels */
  2198.               if hn_outlines.mmh=0 then hn_outlines.mmh=1
  2199.            end /* do */
  2200.            do mmh=hn_level+1 to 7  /* fix up higher levels */
  2201.               hn_outlines.mmh=0
  2202.            end /* do */
  2203.  
  2204.            immh=0 ;aah=''       /* build outline number */
  2205.            do mmh=hn_outline to hn_level
  2206.               immh=immh+1
  2207.               jint=hn_outlines.mmh
  2208.               anums=hn_numbers.immh
  2209.               if words(anums)<jint then
  2210.                 aah=aah||jint
  2211.               else
  2212.                 aah=aah||strip(word(anums,jint))
  2213.               if mmh<hn_level then aah=aah'.'
  2214.            end /* do */
  2215.            ah=aah') 'ah         /* add the outline number */
  2216.         end
  2217.         if  (pos('CENTER',translate(t2a))+pos('MIDDLE',translate(t2a)))>0 & ,
  2218.              length(ah)<Xlinelen then do
  2219.                 docenter=1
  2220.          end
  2221.          else do
  2222.              if HN_LEVEL=1 then do
  2223.                  p1=preh1;p2=posth1
  2224.               end
  2225.               else do
  2226.                    p1=prehn ; p2=posthn
  2227.               end /* do */
  2228.               ah=p1||ah||p2
  2229.          end /* do */
  2230.  
  2231.          ah=translate(ah,' ','0d0a0009'x)
  2232.          if docenter=1 then  ah=center(ah,Xlinelen)
  2233.  
  2234.          call sendout ' '
  2235.          foo=sendout(ah,2,indent,,xlinelen)
  2236.          if HN_LEVEL<4 then call sendout ' '
  2237.          aflag=0
  2238.       end
  2239.  
  2240.       when t2='P' then do
  2241.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2242.          thispara='';aflag=0
  2243.          if lastelem<>'P' then call sendout ' '
  2244.          palign=get_elem_val(t2a,'ALIGN')
  2245.          if palign='CENTER' | palign='MIDDLE' then docenter=1
  2246.          if palign='LEFT' | palign='RIGHT' then docenter=0
  2247.       end /* do */
  2248.  
  2249.  
  2250.        when t2='PRE'  then DO
  2251.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2252.           CALL SENDOUT ' '
  2253.           thispara='' ; aflag=0
  2254.           ispre=1
  2255.        END
  2256.        when t2='/PRE' then DO
  2257.           foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2258.           CALL SENDOUT ' '
  2259.           thispara='' ; aflag=0
  2260.           ispre=0
  2261.        END
  2262.  
  2263.        when t2='DIV'  then do
  2264.           foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2265.           isc=get_elem_val(t2a,'ALIGN')
  2266.           if isc="MIDDLE" | isc="CENTER" then
  2267.               iscenter=1
  2268.           if isc="RIGHT" then iscenter=2
  2269.           thispara='' ; aflag=0
  2270.        end /* do */
  2271.  
  2272.        when t2='/DIV' then do
  2273.           foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2274.           thispara='' ; aflag=0
  2275.           iscenter=0
  2276.        end
  2277.  
  2278.        when t2='CENTER' then do
  2279.           foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2280.           thispara='' ; aflag=0
  2281.           iscenter=1
  2282.         end
  2283.  
  2284.        when t2='/CENTER' then do
  2285.           foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2286.           thispara='' ; aflag=0
  2287.           iscenter=0
  2288.         end
  2289.  
  2290.       when t2='TEXTAREA' then do
  2291.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2292.          thispara='';aflag=0
  2293.          ah=getelem('/TEXTAREA')
  2294.          ah=remove_htmls(ah)
  2295.          ncols=get_elem_val(t2a,'COLS')
  2296.          if datatype(ncols)<>'NUM' then ncols=50
  2297.          ah2=box_around(ah,min(ncols,Xlinelen-3))
  2298.          foo=sendout(ah2,1)
  2299.          aflag=0
  2300.       end
  2301.  
  2302.       when t2='BLOCKQUOTE' then do
  2303.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2304.          call sendout ' '
  2305.          thispara='';aflag=0
  2306.          indent=indent+indent3 ; rightindent=rightindent+indent3
  2307.       end
  2308.  
  2309.       when t2='/BLOCKQUOTE' then do
  2310.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2311.          thispara='';aflag=0
  2312.          call sendout ' '
  2313.          indent=max(0,indent-mindent3); rightindent=max(0,rightindent-mindent3)
  2314.       end
  2315.  
  2316.       when wordpos(t2,'UL TL DL OL MENU DIR')>0 then do
  2317.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2318.          listtypes=listtypes' 't2
  2319.          if t2='OL' then OLCNTs=OLCNTs' 0'
  2320.          thispara='';aflag=0
  2321.          i3=3; if xlinelen<25 then i3=1
  2322.  
  2323.          indent=indent+indent3
  2324.      end
  2325.  
  2326.       when wordpos(t2,'/UL /DL /OL /MENU /DIR /TL ')>0 then do
  2327.          IW=WORDS(LISTTYPES)
  2328.          LASTT=WORD(LISTTYPES,IW)
  2329.  
  2330.          IF lastt<>SUBSTR(T2,2) then do
  2331.               indent=0 ; olcnts='' ; listtypes=''
  2332.               call do_display_error 1 ,  "Warning: expected "||t2||"; found /"||lastt , ,
  2333.                                          T2"_NOT_"lastt
  2334.          end /* do */
  2335.  
  2336. /* legit list .. */
  2337.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2338.          thispara=' '         ; aflag=0
  2339.  
  2340. /* shrink list infos */
  2341.          if lastt='OL' then do
  2342.              iw2=words(olcnts)
  2343.              if iw2=1 then
  2344.                 olcnts=''
  2345.              else
  2346.                 olcnts=delword(olcnts,iw2)
  2347.          end
  2348.          if iw=1 then                 /* fix list of UL OL */
  2349.                 listtypes=''
  2350.          else
  2351.                listtypes=delword(listtypes,iw)
  2352.          indent=max(0,indent-mindent3)
  2353.          if t2='/DL' & ddon=1 then indent=max(0,indent-mindent3)
  2354.  
  2355.          call sendout ' '
  2356.  
  2357.       end               /* /ul etc */
  2358.  
  2359.       when t2='LI'  then do
  2360.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2361.          aflag=figflag(listtypes)       /* the flag for this type */
  2362.          thispara=''
  2363.          call sendout ' '
  2364.       end /* do */
  2365.  
  2366.       when t2='DD' | t2='DT' then do
  2367.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2368.          goon=words(listtypes)
  2369.          if word(listtypes,goon)<>'DL' then do
  2370.               SAY ' '
  2371.               indent=0 ; olcnts='' ; listtypes=''
  2372.               call do_display_error 1, "Warning: DD or DT not expected in  list " , "UNEXPECTED_DD|DT"
  2373.          end
  2374.          aflag=' '
  2375.          if t2='DT' then do
  2376.              if ddon=1 then indent=max(0,indent-mindent3)
  2377.              ddon=0
  2378.          end
  2379.          if t2='DD' then do
  2380.               indent=indent+indent3
  2381.               ddon=1
  2382.          end
  2383.          thispara=''
  2384.          call sendout ' '
  2385.       end /* do */
  2386.  
  2387.       when t2='SELECT' then do
  2388.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2389.          selsize=get_elem_val(t2a,'SIZE')
  2390.          if datatype(selsize)<>"NUM" | showallopts=1 then
  2391.              listtypes=listtypes' 't2
  2392.          else
  2393.              listtypes=listtypes' 't2||(selsize+1)
  2394.          thispara='';aflag=0
  2395.          ijm=max(1,xlinelen-(indent+rightindent+4))
  2396.  
  2397.          ijm=min(ijm,14)
  2398.          if  lineart>=0 then
  2399.             foo3=d2c(218)||copies(d2c(196),ijm)  /* ||d2c(191) */
  2400.          else
  2401.             foo3='/'||copies('-',ijm)   /* ||'\' */
  2402.          foo=sendout(foo3,0,indent,,xlinelen)
  2403.  
  2404.          indent=indent+1
  2405.  
  2406.       end
  2407.  
  2408.       when t2='OPTION' then do
  2409.          goon=words(listtypes)
  2410.          ggw=word(listtypes,goon)
  2411.          if abbrev(ggw,'SELECT')=0 then do      /* SELECT not active */
  2412.               indent=0 ; olcnts='' ; listtypes=''
  2413.               call display_error 1,"Warning: Option not expected in list" , "UNEXPECTED_OPTION"
  2414.               iterate
  2415.          end
  2416.  
  2417. /* check selsize counter */
  2418.          parse var ggw 'SELECT' ggw2
  2419.          showok=0
  2420.          if ggw='SELECT' then do
  2421.             showok=1
  2422.          end
  2423.          else do
  2424.             if datatype(ggw2)='NUM' then do
  2425.                if ggw2>0  then do
  2426.                    showok=1
  2427.                    if ggw2=1 then showok=2
  2428.                    jt3=ggw2-1 /* count down */
  2429.                    ggw3='SELECT'||jt3
  2430.                    listtypes=delword(listtypes,goon)' 'ggw3
  2431.                end /* do */
  2432.             end
  2433.          end
  2434.          if showok=1 then do    /* SIZE not violated */
  2435.               foo=sendout(thispara,ispre,indent+1,aflag,xlinelen)
  2436.               aflag=flagselect
  2437.               if pos('SELECTED',translate(t2a))>0 then aflag=flagselect2
  2438.               thispara=''
  2439.           end         /* else, SIZE shown already */
  2440.           else do
  2441.              if showok=2 then DO
  2442.                thispara=prea||'...more'||posta /* this is the ..more.. flag */
  2443.                foo=sendout(thispara,ispre,indent+1,aflag,xlinelen)
  2444.              END
  2445.              thispara='' ; AFLAG=''  /* zap this option text */
  2446.           end /* do */
  2447.       end /* do */
  2448.  
  2449.  
  2450.      WHEN T2='/SELECT' then DO
  2451.          IW=WORDS(LISTTYPES)
  2452.          LASTT=WORD(LISTTYPES,IW)
  2453.          IF abbrev(lastt,'SELECT')=0 then do
  2454.               call do_display_error 1, "Warning: expected "||t2||"; found /"||lastt , "UNEXPECTED_/SELECT"
  2455.               indent=0 ; olcnts='' ; listtypes=''
  2456.               iterate
  2457.          end /* do */
  2458.  
  2459. /* legit list .. WITHIN SIZE?*/
  2460.          if right(lastt,1)<>'0' then
  2461.             foo=sendout(thispara,ispre,indent+1,aflag,xlinelen)
  2462.  
  2463.          thispara=' '         ; aflag=0
  2464.          if iw=1 then                 /* fix list of UL OL */
  2465.                 listtypes=''
  2466.          else
  2467.                listtypes=delword(listtypes,iw)
  2468.  
  2469.          indent=max(0,indent-1)
  2470.  
  2471.          ijm=max(1,xlinelen-(indent+rightindent+4))
  2472.  
  2473.          ijm=min(ijm,14)
  2474.          if  lineart>=0 then
  2475.                 foo3=d2c(192)||copies(d2c(196),ijm) /*||d2c(217) */
  2476.          else
  2477.                 foo3='\'||copies('-',ijm)   /* ||'/' */
  2478.          foo=sendout(foo3,0,indent,,xlinelen)
  2479.       end
  2480.  
  2481.  
  2482.  
  2483.       when t2='BR' then do
  2484.          foo=sendout(thispara,ispre,indent,aflag,xlinelen)
  2485.          thispara='';aflag=0
  2486.       end /* do */
  2487.  
  2488. /* paragraph modifiers */
  2489.        when t2='A' then  do
  2490.              if pos('NAME=',translate(t2a))=0 then do
  2491.                 anchoron2=0
  2492.                 if anchoron=1 then do           /* warning */
  2493.                     call do_display_error 0,"Warning: unclosed <A> ", "UNCLOSED_<A>"
  2494.                     anchoron2=1                /* assume we are preceded by a </a> */ 
  2495.                 end /* do */
  2496.                 anchoron=1 ;anchoron1=1 
  2497.              end
  2498.        end
  2499.        when t2='/A' then  do
  2500.           if anchoron=1 then anchoron2=1
  2501.           anchoron=0 ;anchoron1=0
  2502.        end
  2503.  
  2504. /* LOGICAL ELEMENTS */
  2505.        when pos(t2,docaps' 'douline' 'doquote)>0 then do        /* a font modifer */
  2506.            if wordpos(t2,docaps)>0 then capon=capon+1
  2507.            if wordpos(t2,douline)>0 then ulineon=ulineon+1
  2508.            if wordpos(t2,doquote)>0 then do
  2509.                 quoteon=quoteon+1 ;quoteon1=1 ; QUOTEON2=0
  2510.             end
  2511.        end /* do */
  2512.  
  2513. /* END LOGICAL ELEMENTS */
  2514.        when pos(t2end,docaps' 'douline' 'doquote)>0 then do        /* end of font modifer */
  2515.           if wordpos(t2end,docaps)>0 then capon=max(0,capon-1)
  2516.  
  2517.           if wordpos(t2end,douline)>0 then ulineon=max(0,ulineon-1)
  2518.           if wordpos(t2end,doquote)>0 then do
  2519.              IF QUOTEON=1 then QUOTEON2=1   /* this is the end of nested emphasis */
  2520.              quoteon=max(quoteon-1,0) ;quoteon1=0
  2521.           end
  2522.           if t1<>' ' then thispara=' 'thispara
  2523.  
  2524.        end
  2525.  
  2526.       when t2='INPUT' then do
  2527.  
  2528.           atype=TRANSLATE(get_elem_val(t2a,'TYPE'))
  2529.  
  2530.           IF ATYPE='' then ATYPE='TEXT'
  2531.           avalue=get_elem_val(t2a,'VALUE',1)
  2532.           if atype='RADIO' then do
  2533.              if wordpos('CHECKED',translate(t2a))>0 then
  2534.                  thispara=thispara' 'radioboxcheck
  2535.              else
  2536.                  thispara=thispara' 'radiobox
  2537.           end
  2538.           if atype='CHECKBOX' then do
  2539.              if wordpos('CHECKED',translate(t2a))>0 then
  2540.                  thispara=thispara' 'checkboxcheck' '
  2541.              else
  2542.                  thispara=thispara' 'checkbox' '
  2543.           end
  2544.           if atype='TEXT' then do
  2545.                av2=get_elem_val(t2a,'SIZE')
  2546.                if av2='' then av2=get_elem_val(t2a,'MAXLENGTH')
  2547.                if av2='' then av2=4
  2548.                atextmark=textmark1||copies(textmark,av2)||textmark2
  2549.                thispara=thispara' 'atextmark
  2550.           end
  2551.           if atype='SUBMIT' then do
  2552.              if avalue='' then avalue='SUBMIT'
  2553.              thispara=thispara' '||submitmark1||strip(avalue)||submitmark2
  2554.           end /* do */
  2555.           if atype='RESET' then do
  2556.              if avalue='' then avalue='RESET'
  2557.              thispara=thispara' 'submitmark1||strip(avalue)||submitmark2
  2558.           end /* do */
  2559.  
  2560.        end /* do */
  2561.  
  2562.        otherwise nop
  2563.     end  /* select */
  2564.  
  2565. return 1                /* results saved in thispara */
  2566.  
  2567.  
  2568. /*************/
  2569. /* display error? */
  2570. do_display_error:
  2571. parse arg serious,amess,err2
  2572. if display_errors=0 then return 1       /* write nothing */
  2573.  
  2574. say amess               /* write to screen */
  2575.  
  2576. if display_errors=1 & serious<>1 then return 1  /* do not record to file */
  2577. if display_errors=3 then errflag=errorflag||err2
  2578. ioo=sendout(eRRflag' 'thispara,ispre,indent,aflag,xlinelen)
  2579. say " "
  2580. thispara=' ' ; aflag=0
  2581. return 1
  2582.  
  2583.  
  2584. /***************************/
  2585. /* say help */
  2586. sayhelp:
  2587. say ''
  2588. say "          "cy_ye||copies('/',25)||copies('\',25)|| normal
  2589. say "                    "bold"HTML_TXT: An HTML to text convert"normal
  2590. say " "
  2591. say bold"HTML_TXT "normal" is used to convert an "bold"HTML"normal" file to a "bold"text"normal" file. "
  2592. say " "
  2593. say bold"HTML_TXT"normal" will attempt to maintain the format of the HTML document "
  2594. say "by using appropriate spacing and ASCII characters. "
  2595. say " "
  2596. say bold"HTML_TXT"normal" can use ASCII art (lines and boxes), as well as other high-ascii "
  2597. say "characters, to improve the appearance of the output (text) file."
  2598. say " "
  2599. say bold"HTML_TXT"normal" can be customized in a number of ways. For example, you can:"
  2600. say " * suppress the use of line art and other high ASCII characters (your output"
  2601. say "   will be rougher, but will suffer from fewer compatability problems)."
  2602. say " * display tables (including nested tables) in a tabular format, or as "
  2603. say "   ordered lists"
  2604. say " * change the bullet characters used in ordered lists "
  2605. say ' * display Hn "headers" as an hierarchical outline '
  2606. say " * change characters used to signify logical elements (emphasis, anchors, etc.)"
  2607. say " "
  2608. say " "
  2609. say cy_YE " ... hit ENTER key for more " NORMAL
  2610. parse pull xx
  2611. say " ";say " " ; say " " ; say " "; say " "; say " "; 
  2612. say bold" Usage Hints: "normal
  2613. say " "
  2614. SAY " * "reverse"Quick file list:"normal" enter "bold"/DIR file.ext"normal" (for example: "bold"/DIR *.HTM /p"normal
  2615. say " "
  2616. SAY " * "reverse"To change a parameter:"normal" enter "bold"/VAR var1=val1"normal" (for example: "bold"/VAR lineart=0 "normal
  2617. say " "
  2618. SAY " * "reverse"Command line mode:"normal" Specify input (html) and output (text) file"
  2619. say "         "bold"Example: "normal"D:\>HTM_TXT2 foo.htm foo.txt "
  2620. say " "
  2621. say "    ... or, to modify the default parameters, add "bold" /VAR var1=val1 ; var2=val2  "normal
  2622. say "         "bold"Example: "normal"D:\>HTM_TXT2 foo.htm foo.txt /VAR lineart=0 ; flagul=* $ ! "
  2623. say " "
  2624. say " * "bold"You can change the default parameters by editing HTM_TXT2.CMD "
  2625. say " "
  2626. say cy_ye " *  This is the less complete, but  quicker, version of HTML_TXT"normal
  2627. say " "
  2628. say "            "cy_ye||copies('\',25)||copies('/',25)|| normal
  2629. say " " ; say " "
  2630.  
  2631. return 1
  2632.  
  2633.  
  2634.