This is a big patch, I have thoroughly tested it and man pages generate 
perfectly. The only problem that I've encountered, is that it writes a lot of 
nonsense to stderr, mostly warnings that it could not find a translation 
database. I am leaving the (disabled) extra copy of instant in dbtoman just in 
case anyone wants to see if there is anything else that can be taken from it, 
but most of the remaining code is seemingly redundant or useless, so if there 
are no qualms about it, I will remove it in another patch.

Thank you for your time,
-Chase
From aa04fb492c27457d70d785028d7675d0e7b1fda8 Mon Sep 17 00:00:00 2001
From: chase <ch...@localhost.com>
Date: Tue, 23 Oct 2018 20:02:15 -0500
Subject: [PATCH] Merge dbtoman/instant with dtdocbook/instant

---
 cde/doc/util/dbtoman/Imakefile                |    2 +-
 cde/doc/util/dbtoman/dbtoman                  |    2 +-
 .../util/dbtoman/transpec/docbook-to-man.ts   |  106 +-
 cde/programs/dtdocbook/README                 |    9 -
 cde/programs/dtdocbook/doc2sdl/dtdocbook      |    2 +-
 cde/programs/dtdocbook/instant/README         |    1 +
 cde/programs/dtdocbook/instant/browse.c       |    5 -
 cde/programs/dtdocbook/instant/general.h      |   19 +-
 cde/programs/dtdocbook/instant/info.c         |    5 -
 cde/programs/dtdocbook/instant/main.c         |   47 +-
 cde/programs/dtdocbook/instant/tables.c       | 1979 +++++++++++++----
 cde/programs/dtdocbook/instant/traninit.c     |    6 +-
 cde/programs/dtdocbook/instant/translate.c    |    6 +-
 cde/programs/dtdocbook/instant/translate.h    |    7 -
 cde/programs/dtdocbook/instant/tranvar.c      |   32 +-
 cde/programs/dtdocbook/instant/util.c         |    5 -
 16 files changed, 1639 insertions(+), 594 deletions(-)

diff --git a/cde/doc/util/dbtoman/Imakefile b/cde/doc/util/dbtoman/Imakefile
index 30c9d3ac..f395247b 100644
--- a/cde/doc/util/dbtoman/Imakefile
+++ b/cde/doc/util/dbtoman/Imakefile
@@ -3,7 +3,7 @@ XCOMM $XConsortium: Imakefile /main/1 1996/07/23 19:50:00 rws $
 #define IHaveSubdirs
 #define PassCDebugFlags
 
-SUBDIRS = instant
+SUBDIRS = 
 
 MakeSubdirs($(SUBDIRS))
 DependSubdirs($(SUBDIRS))
diff --git a/cde/doc/util/dbtoman/dbtoman b/cde/doc/util/dbtoman/dbtoman
index af4cdb1f..941687ae 100755
--- a/cde/doc/util/dbtoman/dbtoman
+++ b/cde/doc/util/dbtoman/dbtoman
@@ -45,7 +45,7 @@ PARSER_OPTS="-g -oline -wno-idref"
 SGML_CATALOG_FILES="$SGML/catalog"
 export SGML_CATALOG_FILES
 
-INSTANT=$CDETOP/doc/util/dbtoman/instant/instant
+INSTANT=$CDETOP/programs/dtdocbook/instant/instant
 INSTANT_OPT=-d
 
 DECL=$CDETOP/programs/dtdocbook/doc2sdl/docbook.sgml
diff --git a/cde/doc/util/dbtoman/transpec/docbook-to-man.ts b/cde/doc/util/dbtoman/transpec/docbook-to-man.ts
index baed6119..662e19ec 100644
--- a/cde/doc/util/dbtoman/transpec/docbook-to-man.ts
+++ b/cde/doc/util/dbtoman/transpec/docbook-to-man.ts
@@ -55,9 +55,9 @@ Var:	procsubstep 0
 #
 GI:		REFENTRY
 StartText:	^.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n
-		^.TH "${_followrel descendant REFENTRYTITLE 1000}"
-		"${_followrel descendant MANVOLNUM 1000}"^
-EndText:	^...\\" created by instant / docbook-to-man, ${date}^
+		^.TH "@{_followrel descendant REFENTRYTITLE 1000}"
+		"@{_followrel descendant MANVOLNUM 1000}"^
+EndText:	^...\\" created by instant / docbook-to-man, @{date}^
 -
 #
 GI:		DOCINFO
@@ -89,8 +89,8 @@ Ignore:		all
 -
 #
 GI:		REFNAME
-StartText:	${_isset refnameseen xxx 20}
-EndText:	${_set refnameseen xxx}
+StartText:	@{_isset refnameseen xxx 20}
+EndText:	@{_set refnameseen xxx}
 -
 #
 GI:		_refname
@@ -114,17 +114,17 @@ EndText:	^
 -
 #
 GI:		REFSECT1
-StartText:	^.SH "${_followrel child TITLE 1000}"^
+StartText:	^.SH "@{_followrel child TITLE 1000}"^
 EndText:	^
 -
 #
 GI:		REFSECT2
-StartText:	^.SS "${_followrel child TITLE 1000}"^
+StartText:	^.SS "@{_followrel child TITLE 1000}"^
 EndText:	^
 -
 #
 GI:		REFSECT3
-StartText:	^.SS "${_followrel child TITLE 1000}"^
+StartText:	^.SS "@{_followrel child TITLE 1000}"^
 EndText:	^
 -
 #
@@ -715,12 +715,12 @@ EndText:	^.RE^
 -
 #
 GI:		ORDEREDLIST
-StartText:	${_set orderlist 1}
+StartText:	@{_set orderlist 1}
 -
 #
 GI:		LISTITEM
 Context:	ORDEREDLIST
-StartText:	^.IP "\ \ \ ${orderlist}." 6^
+StartText:	^.IP "\ \ \ @{orderlist}." 6^
 Increment:	orderlist
 -
 #
@@ -847,43 +847,43 @@ Context:	VARLISTENTRY
 #
 GI:		SEGMENTEDLIST
 Relation:	ancestor ITEMIZEDLIST
-StartText:	^.RS^${_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
+StartText:	^.RS^@{_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
 EndText:	^.TE^.RE^
 -
 #
 GI:		SEGMENTEDLIST
 Relation:	ancestor GLOSSLIST
-StartText:	^.RS^${_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
+StartText:	^.RS^@{_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
 EndText:	^.TE^.RE^
 -
 #
 GI:		SEGMENTEDLIST
 Relation:	ancestor ORDEREDLIST
-StartText:	^.RS^${_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
+StartText:	^.RS^@{_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
 EndText:	^.TE^.RE^
 -
 #
 GI:		SEGMENTEDLIST
 Relation:	ancestor SIMPLELIST
-StartText:	^.RS^${_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
+StartText:	^.RS^@{_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
 EndText:	^.TE^.RE^
 -
 #
 GI:		SEGMENTEDLIST
 Relation:	ancestor VARIABLELIST
-StartText:	^.RS^${_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
+StartText:	^.RS^@{_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
 EndText:	^.TE^.RE^
 -
 #
 GI:		SEGMENTEDLIST
 Relation:	ancestor SEGMENTEDLIST
-StartText:	^.RS^${_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
+StartText:	^.RS^@{_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
 EndText:	^.TE^.RE^
 -
 #
 GI:		SEGMENTEDLIST
 Relation:	child TITLE
-StartText:	^${_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
+StartText:	^@{_followrel child TITLE 400}^.TS^tab();^l l l l l l l l l l l l l l l l l l.^
 EndText:	^.TE^
 -
 #
@@ -915,7 +915,7 @@ EndText:	
 #
 GI:		PROCEDURE
 #	defer to the content...
-StartText:	${_set procstep 1}${_set procsubstep 1}
+StartText:	@{_set procstep 1}@{_set procsubstep 1}
 -
 #
 GI:		TITLE
@@ -926,13 +926,13 @@ EndText:	\\fR^
 #
 GI:		STEP
 Context:	SUBSTEPS
-StartText:	^.PP^\\fISubstep ${procsubstep}.\s\s
+StartText:	^.PP^\\fISubstep @{procsubstep}.\s\s
 EndText:	^
 Increment:	procsubstep 1
 -
 #
 GI:		STEP
-StartText:	^.PP^\\fIStep ${procstep}.\s\s
+StartText:	^.PP^\\fIStep @{procstep}.\s\s
 EndText:	^
 Increment:	procstep 1
 -
@@ -949,7 +949,7 @@ EndText:	^.RE^
 -
 #
 GI:		CALLOUTLIST
-StartText:	${_set callout 1}
+StartText:	@{_set callout 1}
 #	nothing to do specifically, defer to the content...
 -
 #
@@ -960,7 +960,7 @@ EndText:	\\fR^.PP^
 -
 #
 GI:		CALLOUT
-StartText:	^.PP^\\fICallout ${callout}.\s\s\\fR
+StartText:	^.PP^\\fICallout @{callout}.\s\s\\fR
 EndText:	^
 Increment:	callout
 -
@@ -1180,24 +1180,24 @@ EndText:	^
 GI:		ARG
 Context:	GROUP
 NthChild:	1
-EndText:	${_attval REP REPEAT 505}\s
+EndText:	@{_attval REP REPEAT 505}\s
 -
 #
 GI:		ARG
 Context:	GROUP
 StartText:	\s|\s
-EndText:	${_attval REP REPEAT 505}\s
+EndText:	@{_attval REP REPEAT 505}\s
 -
 #
 GI:		ARG
 AttValue:	CHOICE OPT
 StartText:	\s[
-EndText:	${_attval REP REPEAT 505}]\s
+EndText:	@{_attval REP REPEAT 505}]\s
 -
 #
 GI:		ARG
 #	no special attrs -- just pass content through
-EndText:	${_attval REP REPEAT 505}\s
+EndText:	@{_attval REP REPEAT 505}\s
 -
 #
 GI:		_arg_group
@@ -1209,30 +1209,30 @@ Ignore:		all
 GI:		GROUP
 AttValue:	CHOICE OPT
 StartText:	\s[
-EndText:	]\s${_attval REP REPEAT 505}
+EndText:	]\s@{_attval REP REPEAT 505}
 -
 #
 GI:		GROUP
 AttValue:	CHOICE REQ
 StartText:	\s{
-EndText:	}\s${_attval REP REPEAT 505}
+EndText:	}\s@{_attval REP REPEAT 505}
 -
 #
 GI:		GROUP
 AttValue:	CHOICE OPTMULT
 StartText:	\s[[
-EndText:	]]\s${_attval REP REPEAT 505}
+EndText:	]]\s@{_attval REP REPEAT 505}
 -
 #
 GI:		GROUP
 AttValue:	CHOICE REQMULT
 StartText:	\s{{
-EndText:	}}\s${_attval REP REPEAT 505}
+EndText:	}}\s@{_attval REP REPEAT 505}
 -
 #
 GI:		GROUP
 AttValue:	CHOICE PLAIN
-EndText:	${_attval REP REPEAT 505}
+EndText:	@{_attval REP REPEAT 505}
 -
 #
 GI:		SBR
@@ -1246,7 +1246,7 @@ GI:		SYNOPFRAGMENT
 GI:		SYNOPFRAGMENTREF
 #	WHAT TO DO HERE??   pass through the content, but what about the
 #	linkend?  (will call it across...)
-EndText:	\s\\fI(refers to: ${_followlink LINKEND 1000})\\fR
+EndText:	\s\\fI(refers to: @{_followlink LINKEND 1000})\\fR
 -
 #
 GI:		FUNCSYNOPSIS
@@ -1306,12 +1306,12 @@ GI:		LINK
 -
 GI:		OLINK
 StartText:	\\fI
-EndText:	\s(link to external document ${TargetDocEnt})\s\\fR
+EndText:	\s(link to external document @{TargetDocEnt})\s\\fR
 -
 #
 GI:		ULINK
 StartText:	\\fI
-EndText:	\s(link to URL ${URL})\s\\fR
+EndText:	\s(link to URL @{URL})\s\\fR
 -
 #
 GI:		FOOTNOTEREF
@@ -1324,16 +1324,16 @@ GI:		FOOTNOTE
 #
 GI:		XREF
 AttValue:	ENDTERM
-StartText:	\\fI(cross-reference to ``${_followlink ENDTERM 1000}'')\\fR\s
+StartText:	\\fI(cross-reference to ``@{_followlink ENDTERM 1000}'')\\fR\s
 -
 #
 GI:		XREF
-StartText:	\\fI(cross-reference to ``${_followlink LINKEND 600})''\\fR\s
+StartText:	\\fI(cross-reference to ``@{_followlink LINKEND 600})''\\fR\s
 -
 #
 GI:		_xref
 SpecID:		600
-StartText:	${XREFLABEL}
+StartText:	@{XREFLABEL}
 Ignore:		all
 -
 #
@@ -1350,11 +1350,11 @@ GI:		ANCHOR
 #
 GI:		GRAPHIC
 AttValue:	ENTITYREF
-StartText:	^.PP^.if t .P! "${_filename}"^
+StartText:	^.PP^.if t .P! "@{_filename}"^
 -
 #
 GI:		INLINEGRAPHIC
-StartText:	^.if t .P! "${_filename}"^
+StartText:	^.if t .P! "@{_filename}"^
 -
 #
 GI:		INFORMALEQUATION
@@ -1384,14 +1384,14 @@ GI:		INLINEEQUATION
 #
 #
 GI:		INFORMALTABLE
-StartText:	^${_calstable tbl tablestart}^
-EndText:	^${_calstable tbl tableend}^
+StartText:	^@{_calstable tbl tablestart}^
+EndText:	^@{_calstable tbl tableend}^
 -
 #
 GI:		TABLE
-StartText:	^.PP^\\fB${_followrel child TITLE 1000}\\fR
-		^${_calstable tbl tablestart}^
-EndText:	^${_calstable tbl tableend}^
+StartText:	^.PP^\\fB@{_followrel child TITLE 1000}\\fR
+		^@{_calstable tbl tablestart}^
+EndText:	^@{_calstable tbl tableend}^
 -
 #
 GI:		TITLE
@@ -1401,8 +1401,8 @@ Ignore:		all
 -
 #
 GI:		TGROUP
-StartText:	^${_calstable tbl tablegroup}^${_followrel child THEAD 700}${_followrel child TBODY 700}${_followrel child TFOOT 701}
-EndText:	${_calstable tbl tablegroupend}
+StartText:	^@{_calstable tbl tablegroup}^@{_followrel child THEAD 700}@{_followrel child TBODY 700}@{_followrel child TFOOT 701}
+EndText:	@{_calstable tbl tablegroupend}
 -
 #
 GI:		COLSPEC
@@ -1425,23 +1425,23 @@ SpecID:		700
 #
 GI:		_tfoot
 SpecID:		701
-StartText:	^${_calstable tbl tablefoot}^
+StartText:	^@{_calstable tbl tablefoot}^
 -
 #
 GI:		ROW
-StartText:	^${_calstable tbl rowstart}
-EndText:	${_calstable tbl rowend}
+StartText:	^@{_calstable tbl rowstart}
+EndText:	@{_calstable tbl rowend}
 -
 #
 GI:		ENTRY
-StartText:	${_calstable tbl entrystart}
-EndText:	${_calstable tbl entryend}
+StartText:	@{_calstable tbl entrystart}
+EndText:	@{_calstable tbl entryend}
 -
 #
 GI:		ENTRYTBL
 StartText:
 EndText:
-Message:	^IMPLEMENT <${_gi} ${_allatts}>^
+Message:	^IMPLEMENT <@{_gi} @{_allatts}>^
 -
 #
 #
@@ -1579,7 +1579,7 @@ EndText:	\\fP
 GI:		CITETITLE
 AttValue:	PUBWORK
 StartText:	\\fI
-EndText:	\\fP (${PUBWORK})\s
+EndText:	\\fP (@{PUBWORK})\s
 -
 #
 GI:		CITETITLE
diff --git a/cde/programs/dtdocbook/README b/cde/programs/dtdocbook/README
index 29908188..805ca4ee 100644
--- a/cde/programs/dtdocbook/README
+++ b/cde/programs/dtdocbook/README
@@ -56,12 +56,3 @@ The directories here are:
 	     convenience during the snapshot only.  These files will
 	     eventually be put in a location common to both dtinfo and
 	     dtdocbook.]
-
-    sgmls
-
-	[C source code for the program "sgmls", an SGML parser.]
-
-    tcl
-
-	[C source code for the Tool Command Language (Tcl) library,
-	 libtcl.a, to be linked into "instant".]
diff --git a/cde/programs/dtdocbook/doc2sdl/dtdocbook b/cde/programs/dtdocbook/doc2sdl/dtdocbook
index 727a0769..594810d0 100755
--- a/cde/programs/dtdocbook/doc2sdl/dtdocbook
+++ b/cde/programs/dtdocbook/doc2sdl/dtdocbook
@@ -395,7 +395,7 @@ fi
 
 
 # The run of instant(1) succeeded. Run dthelp_htag2(1) to create the
-# generated elements (e.g., the list of ids or LOIDS), incorporate the 
+# generated elements (e.g., the list of ids or LOIDS), incorporate the
 # table of semantics and styles (TOSS) and do the compression, if
 # requested.
 if (( $uncompressed )); then
diff --git a/cde/programs/dtdocbook/instant/README b/cde/programs/dtdocbook/instant/README
index 35f3c322..76577205 100644
--- a/cde/programs/dtdocbook/instant/README
+++ b/cde/programs/dtdocbook/instant/README
@@ -35,6 +35,7 @@ Files for instant program
     ------		--------
     browse.c		interactive browser
     general.h		general definitions
+    hyper.c		unknown
     info.c		print information about the instances
     main.c		main entry, arg parsing, instance reading
     tables.c		table-specific formatting routines (TeX and tbl)
diff --git a/cde/programs/dtdocbook/instant/browse.c b/cde/programs/dtdocbook/instant/browse.c
index cef5a759..02cfe555 100644
--- a/cde/programs/dtdocbook/instant/browse.c
+++ b/cde/programs/dtdocbook/instant/browse.c
@@ -48,11 +48,6 @@
  * ________________________________________________________________________
  */
 
-#ifndef lint
-static char *RCSid =
-  "$XConsortium: browse.c /main/3 1996/06/19 17:13:03 drk $";
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
diff --git a/cde/programs/dtdocbook/instant/general.h b/cde/programs/dtdocbook/instant/general.h
index 413e9aab..df09ba8e 100644
--- a/cde/programs/dtdocbook/instant/general.h
+++ b/cde/programs/dtdocbook/instant/general.h
@@ -45,13 +45,6 @@
  * ________________________________________________________________________
  */
 
-#ifdef STORAGE
-#ifndef lint
-static char *gen_h_RCSid =
-  "$XConsortium: general.h /main/11 1996/08/08 14:41:50 cde-hp $";
-#endif
-#endif
-
 /* get Tcl header so the variables make sense */
 #include <tcl.h>
 
@@ -133,6 +126,18 @@ typedef enum {
 #define IMS_attnames		50
 #define IMS_elemnames		50
 
+/* ----- typedef and other misc definitions ----- */
+
+#ifndef TRUE
+#define TRUE (1 == 1)
+#endif
+
+#ifndef FALSE
+#define FALSE (1 == 0)
+#endif
+
+typedef short bool;
+
 /* ----- structure definitions ----- */
 
 /*  We use this for variables, attributes, etc., so the caller only needs an
diff --git a/cde/programs/dtdocbook/instant/info.c b/cde/programs/dtdocbook/instant/info.c
index 33f4310e..85cf0c66 100644
--- a/cde/programs/dtdocbook/instant/info.c
+++ b/cde/programs/dtdocbook/instant/info.c
@@ -54,11 +54,6 @@
  * ________________________________________________________________________
  */
 
-#ifndef lint
-static char *RCSid =
-  "$XConsortium: info.c /main/3 1996/06/19 17:13:13 drk $";
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
diff --git a/cde/programs/dtdocbook/instant/main.c b/cde/programs/dtdocbook/instant/main.c
index 7dfe91c6..06e2fc92 100644
--- a/cde/programs/dtdocbook/instant/main.c
+++ b/cde/programs/dtdocbook/instant/main.c
@@ -59,13 +59,6 @@
  * ________________________________________________________________________
  */
 
-#ifndef lint
-static char *RCSid =
-  "$XConsortium: main.c /main/14 1996/11/27 11:47:17 cde-hp $";
-static char *CopyRt =
- "Copyright 1993 Open Software Foundation, Inc., Cambridge, Mass.  All rights reserved.";
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
@@ -93,6 +86,7 @@ static char *CopyRt =
 #endif
 
 static int	do_context, do_tree, do_summ, do_stats, do_validate, do_idlist;
+static int	do_DATAhack = 0;
 static char	*this_prog;
 static char	*in_file, *out_file;
 static char	*tranfile;
@@ -101,6 +95,8 @@ static char	*start_id;
 static char	*last_file;
 static int	last_lineno;
 
+extern int	BOFTTextThresh;
+
 /* forward references */
 static void	HandleArgs(int, char *[]);
 static void	Initialize1();
@@ -142,9 +138,7 @@ if ((_DtLcxOpenAllDbs(&myDb) != 0)) {
 ret = _DtXlateGetXlateEnv(myDb,myPlatform,&execVer,&compVer);
 if (ret != 0) {
     fprintf(stderr,
-            "Fatal: could not open locale translation database. %d\n", ret);
-
-    exit(1);
+            "Warning: could not open locale translation database. %d\n", ret);
 }
 
 if (_DtLcxXlateStdToOp(myDb,
@@ -213,7 +207,7 @@ main(
 		      TclReadLocaleStrings,
 		      0,
 		      0);
-    
+
     ReadInstance(in_file);
 
     if (interactive) {
@@ -503,18 +497,17 @@ Initialize2(void)
     if (do_validate)
 	out_file = "/dev/null"; /* toss all but error output */
 
-    if (!out_file) {
-	out_file = "out.sdl";
-    }
-
-    if (!(outfp = freopen(out_file, "w", stdout))) {
-	fprintf(stderr,
-		"Could not re-open output '%s' file for writing.\n%s",
-		out_file,
-		strerror(errno));
-	exit(1);
-    }
+    if (out_file){
+	if (!(outfp = freopen(out_file, "w", stdout))) {
+	    fprintf(stderr,
+		    "Could not re-open output '%s' file for writing.\n%s",
+		    out_file,
+		    strerror(errno));
+	    exit(1);
+	}
     SetMappingNV(Variables, "basename", GetOutFileBaseName());
+    }
+    else outfp = stdout;
 }
 
 /* ______________________________________________________________________ */
@@ -596,7 +589,7 @@ HandleArgs(
     char       **thisopt;
     int          count;
 
-    while ((c=getopt(ac, av, "t:vc:s:o:huSxIl:bHVWi:D:Z")) != EOF) {
+    while ((c=getopt(ac, av, "df:t:vc:s:o:huSxIl:bHVWi:D:Z")) != EOF) {
 	switch (c) {
 	    case 't': tranfile		= optarg;	break;
 	    case 'v': do_validate	= 1;		break;
@@ -620,7 +613,7 @@ HandleArgs(
 		*thisopt = strdup(optarg);
 		break;
 	        }
-	    case 'c': 
+	    case 'c':
 		{
 		if (thisopt = cmapfile)
 		    {
@@ -648,6 +641,8 @@ HandleArgs(
 	    case 'l': tpt_lib		= optarg;	break;
 	    case 'i': start_id		= optarg;	break;
 	    case 'o': out_file		= optarg;	break;
+	    case 'd': do_DATAhack	= 1;		break;
+	    case 'f': BOFTTextThresh	= atoi(optarg); break;
 	    case 'b': interactive	= 1;		break;
 	    case 'W': warnings		= 0;		break;
 	    case 'V': verbose		= 1;		break;
@@ -1112,6 +1107,10 @@ ReadESIS(
 		fgets(buf, LINESIZE, fp);
 		i18nBuf = EscapeI18NChars(buf);
 		stripNL(i18nBuf);
+                if (do_DATAhack && (i18nBuf[0] == '\\') && (i18nBuf[1] == 'n') ){
+                        i18nBuf[0] = -1;            /* simulate "^" command */
+                        memmove(&i18nBuf[1], &i18nBuf[2], strlen(i18nBuf)-1);
+                }
 		cont[ncont].ch.data = strdup(i18nBuf);
 		cont[ncont].type = CMD_DATA;
 		ncont++;
diff --git a/cde/programs/dtdocbook/instant/tables.c b/cde/programs/dtdocbook/instant/tables.c
index 9e67e036..86c87975 100644
--- a/cde/programs/dtdocbook/instant/tables.c
+++ b/cde/programs/dtdocbook/instant/tables.c
@@ -20,6 +20,7 @@
  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  * Floor, Boston, MA 02110-1301 USA
  */
+/* $XConsortium: tables.c /main/3 1996/12/07 13:15:23 rws $ */
 /*
  *  Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
  *  All rights reserved.
@@ -39,22 +40,52 @@
  * suitability of this software for any purpose.  It is provided "as is" 
  * without express or implied warranty. 
  */
+/*
+ * Copyright (c) 1996 X Consortium
+ * Copyright (c) 1995, 1996 Dalrymple Consulting
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ * 
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+ * X CONSORTIUM OR DALRYMPLE CONSULTING BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ * 
+ * Except as contained in this notice, the names of the X Consortium and
+ * Dalrymple Consulting shall not be used in advertising or otherwise to
+ * promote the sale, use or other dealings in this Software without prior
+ * written authorization.
+ */
 /* ________________________________________________________________________
  *
  *  Program to manipulate SGML instances.
  *
- *  This module is for handling OSF table markup, printing TeX or tbl
+ * Originally coded for OSF DTD tables, now recoded (fld 3/27/95)
+ * for CALS-type tables (fragment taken from the DocBook DTD).  Then,
+ * *really* upgraded to CALS tables by FLD on 5/28/96.
+ *
+ *  This module is for handling table markup, printing TeX or tbl
  *  (tbl) markup to the output stream.  Also, table markup checking is
  *  done here.  Yes, this depends on the DTD, but it makes translation
- *  specs much cleaner (and makes some things possible.
+ *  specs much cleaner (and makes some things possible).
  *
  *  Incomplete / not implemented / limitations / notes:
  *	vertical alignment (valign attr)
  *	vertical spanning
- *	'wrap hint' attribute
  *	row separators are for the whole line, not per cell (the prog looks
  *		at rowsep for the 1st cell and applies it to the whole row)
- *	trusts that units if colwidths are acceptable to LaTeX and tbl
+ *	trusts that units in colwidths are acceptable to LaTeX and tbl
  *	"s" is an acceptable shorthand for "span" in model attributes
  *
  *  A note on use of OutputString():  Strings with backslashes (\) need lots
@@ -63,11 +94,6 @@
  * ________________________________________________________________________
  */
 
-#ifndef lint
-static char *RCSid =
-  "$XConsortium: tables.c /main/3 1996/06/19 17:13:17 drk $";
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
@@ -81,23 +107,118 @@ static char *RCSid =
 #include "translate.h"
 
 /* text width of page, in inches */
-#define TEXTWIDTH	6.0
+#define TEXTWIDTH	5.5
 #define MAXCOLS		100
 #define SPAN_NOT	0
 #define SPAN_START	1
 #define SPAN_CONT	2
 
-/* these cover the attributes on the table element */
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+/*table parameters */
+
+#define TBLMAXCOL	30	/* max number of columns in tbl table */
+#define NAMELEN		40	/* max length of a name */
+#define BOFTTHRESHOLD	35	/* text length over which to consider
+				 * generating a block of filled text */
+
+
+/* handy declarations */
+
+typedef enum { Left, Right, Center, Justify, Char, Span } tblalign;
+
+typedef enum { TGroup, THead, TFoot, TBody } tblsource;	/* source of a spec */
+
+
+/* table line format information structures */
+
+struct tblcolspec	{
+
+	char		name[NAMELEN];	/* colspec's name */
+	short		num;		/* column number */
+	tblsource	source;		/* where defined */
+
+	tblalign	align;		/* column's alignment */
+	char		alignchar;	/* character for alignment */
+	short		aligncharoff;	/* offset for alignment */
+	char		colwidth[10];	/* width for column */
+	char		colpwidth[10];	/* proportional widths for column */
+	bool		colsep;		/* separator to right of column? */
+	bool		rowsep;		/* separator to bottom of column? */
+	short		moreRows;	/* value for Morerows */
+
+	struct tblcolspec * next;	/* next colspec */
+};
+
+struct tblspanspec	{
+
+	char		name[NAMELEN];	/* spanspec's name */
+	tblsource	source;		/* where defined */
+
+	struct tblcolspec * start;	/* start column */
+	struct tblcolspec * end;	/* end column */
+	tblalign	align;		/* span's alignment */
+	char		alignchar;	/* character for alignment */
+	short		aligncharoff;	/* offset for alignment */
+	bool		colsep;		/* separator to right of column? */
+	bool		rowsep;		/* separator to bottom of column? */
+
+	struct tblspanspec * next;	/* next spanspec */
+};
+
+struct tblformat	{
+	short	count;			/* count of rows matching this spec */
+
+	short	cols;			/* # of columns */
+	short	rowNum;			/* row number */
+	char	colformat[TBLMAXCOL];	/* per-column formats */
+	char	colwidth[TBLMAXCOL][10]; /* per-column widths */
+	char	colpwidth[TBLMAXCOL][10]; /* per-column proportional widths */
+	char	font[TBLMAXCOL][3];	/* column fonts (headers) */
+	bool	colsep[TBLMAXCOL];	/* column separators */
+	bool	rowsep[TBLMAXCOL];	/* row separators */
+	short	moreRows[TBLMAXCOL];	/* moreRows indicator */
+
+	struct tblformat * next;	/* for the next row */
+};
+
+
+/* table state info */
+
+static short	tblcols = 0;		/* number of columns in the table */
+static short	tblrow = 0;		/* the current row in the table */
+
+static bool tblTGroupSeen = FALSE;	/* seen a TGroup in this table yet? */
+
+static char *	tblFrame;		/* table frame info */
+static bool	tblgcolsep;		/* global colsep (in table) */
+static bool	tblgrowsep;		/* global rowsep (in table) */
+
+static int	tblBOFTCount = 0;	/* count of bofts that we've created
+					 * (per table) */
+int	BOFTTextThresh = BOFTTHRESHOLD;
+					/* length of text before we
+					 * call it a BOFT */
+static bool	tblboft = FALSE;	/* within a block of filled text? */
+static bool	tblinBOFT = FALSE;	/* within a boft now? */
+
+static struct tblformat * formP = 0;	/* THead/TBody format lines */
+
+static struct tblcolspec * tblColSpec = 0;   /* colspec structure for table */
+static struct tblspanspec * tblSpanSpec = 0; /* spanspec structure for table */
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
+
+/* these cover the attributes on the Table, TGroup, Colspec elements */
 typedef struct {
-    char	*ncols;
-    char	*halign,    **halign_v;
-    char	*model,     **model_v;
+    char	*cols;
+    char	*align,     **align_v;
     char	*colwidth,  **colwidth_v;
     char	*colsep,    **colsep_v;
-    char	*colweight, **colweight_v;
+    char	*rowsep,    **rowsep_v;
     char	*frame;
-    int		n_halign, n_model, n_colwidth, n_colsep, n_colweight;
-    int		repeathead;	
+    char	*orient;
+    int		pgwide;
+    int		n_align, n_model, n_colwidth, n_colsep;
     int		nc;
 } TableInfo;
 
@@ -112,14 +233,36 @@ static TableInfo	TheTab;
 /* forward references */
 void	SetTabAtts(Element_t *, TableInfo *, int);
 void	FreeTabAtts(TableInfo	*);
+void	ClearTable(TableInfo *);
 void	CheckTable(Element_t *);
-void	TblTable(Element_t *, FILE *);
-void	TblTableCellStart(Element_t *, FILE *);
-void	TblTableCellEnd(Element_t *, FILE *);
-void	TblTableRowStart(Element_t *, FILE *);
-void	TblTableRowEnd(Element_t *, FILE *);
-void	TblTableTop(Element_t *, FILE *);
-void	TblTableBottom(Element_t *, FILE *);
+void	TblTStart(Element_t *, FILE *);
+void	TblTEnd(Element_t *, FILE *);
+void	TblTGroup(Element_t *, FILE *);
+void	TblTGroupEnd(Element_t *, FILE *);
+void	TblTFoot(Element_t *, FILE *);
+void	TblBuildFormat(Element_t *, struct tblformat **, tblsource);
+struct tblformat * TblBuild1Format(Element_t *, bool, tblsource);
+char	TblGetAlign(short, Element_t *, tblsource);
+char *	TblGetWidth(short, Element_t *, bool, tblsource);
+char *	TblGetFont(short, Element_t *, tblsource);
+bool	TblGetColSep(short, Element_t *, tblsource);
+bool	TblGetRowSep(short, Element_t *, tblsource);
+short	TblGetMoreRows(short, Element_t *, tblsource);
+bool	TblColAdv(short, Element_t *, struct tblformat *, tblsource);
+struct tblcolspec * TblEntryColSpec(short, Element_t *, tblsource);
+struct tblspanspec * TblEntrySpanSpec(short, Element_t *, tblsource);
+bool	TblFormatMatch(struct tblformat *, struct tblformat *);
+void	TblPrintFormat(FILE *, struct tblformat *);
+void	TblTRowStart(Element_t *, FILE *);
+void	TblTRowEnd(Element_t *, FILE *);
+void	TblTCellStart(Element_t *, FILE *);
+int	TblCountContent(Element_t *);
+void	TblTCellEnd(Element_t *, FILE *);
+struct tblcolspec * TblDoColSpec(short, Element_t *, struct tblcolspec *, tblsource);
+struct tblspanspec * TblDoSpanSpec(Element_t *, struct tblspanspec *, tblsource);
+struct tblcolspec * TblFindColSpec(char *, tblsource);
+struct tblcolspec * TblFindColNum(short, tblsource);
+struct tblspanspec * TblFindSpanSpec(char *, tblsource);
 void	TexTable(Element_t *, FILE *);
 void	TexTableCellStart(Element_t *, FILE *);
 void	TexTableCellEnd(Element_t *, FILE *);
@@ -129,35 +272,97 @@ void	TexTableTop(Element_t *, FILE *);
 void	TexTableBottom(Element_t *, FILE *);
 
 /* ______________________________________________________________________ */
-/*  Hard-coded stuff for OSF DTD tables.
+/*  Hard-coded stuff for CALS-style DTD tables.
  *  Here are the TABLE attributes (for handy reference):
- *	ncols      NUMBER	num of cells/row should match 
- *	model      CDATA	column prototypes for this table 
- *	colwidth   NUTOKENS	absolute widths of cols 
- *	colweight  NUMBERS	column weights 
- *	halign     CDATA	horiz alignment for columns 
- *	valign     CDATA	vertical alignment for columns 
- *	colsep     NUMBERS	use col separators (lines)? 
- *	rowsep     NUMBERS	use row separators (lines)? 
- *	wrap       NUMBERS	wrap hints for columns
- *	repeathead NUMBER	carry title rows to other pages
- *	frame      (top|bottom|topbot|all|sides|none)	frame style
- *
- *  The 'wrap' attribute is never used.
- *
- *  Usage in transpec: _osftable [tex|tbl|check] ['aspect']
+ *
+ *  Table/InformalTable:
+ *	Colsep	   NUMBER	separate all columns in table?
+ *	Frame	   (Top|Bottom|Topbot|All|Sides|None)	frame style
+ *	Orient	   (Port | Land)	orientation
+ *	Pgwide	   NUMBER	wide table?
+ *	Rowsep	   NUMBER	separate all rows in the table?
+ *	Tabstyle   NMTOKEN	FOSI table style
+ *
+ *  TGroup:
+ *	Align	   (Left|Right|Center|Justify|Char)	alignment of cols
+ *	Char	   CDATA	Alignment specifier
+ *	Charoff	   NUTOKEN	    ""       ""
+ *	Cols	   NUMBER	number of columns
+ *	Colsep	   NUMBER	separate all columns in tgroup?
+ *	Rowsep	   NUMBER	separate all rows in tgroup?
+ *	TGroupstyle NMTOKEN	FOSI table group style
+ *
+ *  Colspec:
+ *	Align      (Left|Right|Center|Justify|Char)	entry align
+ *	Char       CDATA	Alignment specifier
+ *	Charoff    NUTOKEN	    ""       ""
+ *	Colname    NMTOKEN	Column identifier
+ *	Colnum	   NUMBER	number of column
+ *	Colsep     NUMBER	separate this col from next?
+ *	Colwidth   CDATA	width spec
+ *	Rowsep     NUMBER	serarate entry from following row?
+ *
+ *  SpanSpec:
+ *	Align      (Left|Right|Center|Justify|Char)	entry align
+ *	Char       CDATA	Alignment specifier
+ *	Charoff    NUTOKEN	    ""       ""
+ *	Colsep     NUMBER	separate this col from next?
+ *	Nameend    NMTOKEN	name of rightmost col of a span
+ *	Namest     NMTOKEN	name of leftmost col of a span
+ *	Rowsep     NUMBER	serarate entry from following row?
+ *	Spanname   NMTOKEN	name of a horiz. span
+ *
+ *  THead/TFoot/TBody:
+ *	VAlign	   (Top | Middle | Bottom)	group placement
+ *
+ *  Row:
+ *	Rowsep	   NUMBER	separate this row from next?
+ *	VAlign	   (Top | Middle | Bottom)	row placement
+ *
+ *  Entry:
+ *	Align      (Left|Right|Center|Justify|Char)	entry align
+ *	Char       CDATA	Alignment specifier
+ *	Charoff    NUTOKEN	    ""       ""
+ *	Colname    NMTOKEN	Column identifier
+ *	Colsep     NUMBER	separate this col from next?
+ *	Morerows   NUMBER	number of addn'l rows in vert straddle
+ *	Nameend    NMTOKEN	name of rightmost col of a span
+ *	Namest     NMTOKEN	name of leftmost col of a span
+ *	Rotate     NUMBER	90 degree rotation counterclockwise to table?
+ *	Rowsep     NUMBER	serarate entry from following row?
+ *	Spanname   NMTOKEN	name of a horiz. span
+ *	VAlign     (Top | Middle | Bottom)	text vert alignment
+ *  
+ *
+ ** OBSOLETE OSF DTD FORM (still used for TeX form):
+ **  Usage in transpec: _calstable [tex|check|clear] ['aspect']
+ **  where 'aspect' is:
+ **	rowstart	stuff to do at start of a row (tests for spanning)
+ **	rowend		stuff to do at end of a row (eg, rules, etc.)
+ **	cellstart	stuff to do at start of a cell (eg, handle actual
+ **			spanning instructions, etc.)
+ **	cellend		stuff to do at end of a cell  (eg, cell separator)
+ **	top		stuff to do at top of the table
+ **			(like whether or not it needs a starting horiz rule)
+ **	bottom		stuff to do at bottom of the table
+ **			(like whether or not it needs an ending horiz rule)
+ **	(nothing)	the 'cols' param to LaTeX's \begin{tabular}[pos]{cols}
+ **			or 'options' and 'formats' part in tbl
+ *
+ *
+ * New tbl form:
+ *  Usage in transpec: _calstable [tbl] ['aspect']
  *  where 'aspect' is:
- *	rowstart	stuff to do at start of a row (tests for spanning)
- *	rowend		stuff to do at end of a row (eg, rules, etc.)
- *	cellstart	stuff to do at start of a cell (eg, handle actual
- *			spanning instructions, etc.)
- *	cellend		stuff to do at end of a cell  (eg, cell separator)
- *	top		stuff to do at top of the table
- *			(like whether or not it needs a starting horiz rule)
- *	bottom		stuff to do at bottom of the table
- *			(like whether or not it needs an ending horiz rule)
- *	(nothing)	the 'cols' param to LaTeX's \begin{tabular}[pos]{cols}
- *			or 'options' and 'formats' part in tbl
+ *	tablestart	start a table and do style info
+ *	tableend	end the table and clean up
+ *	tablegroup	table TGroup (.T& if not 1st, line format info)
+ *	tablegroupend	end a TGroup
+ *	tablefoot	TFoot within a TGroup
+ *	rowstart	start of a row
+ *	rowend		end of a row
+ *	entrystart	start of an entry (block of filled text, if
+ *				appropriate)
+ *	entryend	end of a cell  (eg, cell separator)
  */
 
 /*  Procedure to
@@ -168,7 +373,7 @@ void	TexTableBottom(Element_t *, FILE *);
  *	Count of args to _osftable
  */
 void
-OSFtable(
+CALStable(
     Element_t	*e,
     FILE	*fp,
     char	**av,
@@ -177,23 +382,33 @@ OSFtable(
 {
     /* Check params and dispatch to appropriate routine */
 
-    if (ac > 1 && !strcmp(av[1], "check")) CheckTable(e);
+    if (!strcmp(av[1], "tbl")) {
 
-    else if (!strcmp(av[1], "tbl")) {
 	if (ac > 2) {
-	    if (!strcmp(av[2], "cellstart"))	TblTableCellStart(e, fp);
-	    else if (!strcmp(av[2], "cellend"))	TblTableCellEnd(e, fp);
-	    else if (!strcmp(av[2], "rowstart")) TblTableRowStart(e, fp);
-	    else if (!strcmp(av[2], "rowend"))	TblTableRowEnd(e, fp);
-	    else if (!strcmp(av[2], "top"))	TblTableTop(e, fp);
-	    else if (!strcmp(av[2], "bottom"))	TblTableBottom(e, fp);
+	    if (!strcmp(av[2], "tablestart"))		TblTStart(e, fp);
+	    else if (!strcmp(av[2], "tableend"))	TblTEnd(e, fp);
+	    else if (!strcmp(av[2], "tablegroup"))	TblTGroup(e, fp);
+	    else if (!strcmp(av[2], "tablegroupend"))	TblTGroupEnd(e, fp);
+	    else if (!strcmp(av[2], "tablefoot"))	TblTFoot(e, fp);
+	    else if (!strcmp(av[2], "rowstart"))	TblTRowStart(e, fp);
+	    else if (!strcmp(av[2], "rowend"))		TblTRowEnd(e, fp);
+	    else if (!strcmp(av[2], "entrystart"))	TblTCellStart(e, fp);
+	    else if (!strcmp(av[2], "entryend"))	TblTCellEnd(e, fp);
 	    else fprintf(stderr, "Unknown %s table instruction: %s\n",
 		av[1], av[2]);
 	}
-	else TblTable(e, fp);
+	else	{
+          fprintf(stderr, "Incomplete %s table instruction\n", av[1]);
+	}
     }
 
     else if (!strcmp(av[1], "tex")) {
+
+        if (ac > 1 && !strcmp(av[1], "check")) CheckTable(e);
+
+        else
+        if (ac > 1 && !strcmp(av[1], "clear")) ClearTable(&TheTab);
+
 	if (ac > 2) {
 	    if (!strcmp(av[2], "cellstart"))	TexTableCellStart(e, fp);
 	    else if (!strcmp(av[2], "cellend"))	TexTableCellEnd(e, fp);
@@ -210,11 +425,23 @@ OSFtable(
     else fprintf(stderr, "Unknown table type: %s\n", av[1]);
 
 }
+
+/*  ClearTable -- start a new table process
+ *
+ */
+
+
+void
+ClearTable( TableInfo * t )
+{
+    memset(t, 0, sizeof(TableInfo));
+}
+
 
 /* ______________________________________________________________________ */
 /*  Set values of the our internal table structure based on the table's
- *  attributes.  (This is also called for rows, since tables and rows
- *  share many of the same attributes.)
+ *  attributes.  (This is called for tables, tgroups, colspecs, and rows,
+ *  since tables and rows share many of the same attributes.)
  *  Arguments:
  *	Pointer to element under consideration.
  *	Pointer table info structure which will be filled in.
@@ -228,18 +455,14 @@ SetTabAtts(
 )
 {
     char	*at;
-
-    memset(t, 0, sizeof(TableInfo));
+    Element_t	* ep;
 
     /* remember values of attributes */
-    if ((at = FindAttValByName(e, "HALIGN")))	  t->halign     = at;
-    if ((at = FindAttValByName(e, "MODEL")))	  t->model      = at;
+    if ((at = FindAttValByName(e, "ALIGN")))	  t->align      = at;
     if ((at = FindAttValByName(e, "COLWIDTH")))	  t->colwidth   = at;
     if ((at = FindAttValByName(e, "COLSEP")))	  t->colsep     = at;
-    if ((at = FindAttValByName(e, "COLWEIGHT")))  t->colweight  = at;
     if ((at = FindAttValByName(e, "FRAME")))	  t->frame      = at;
-    if ((at = FindAttValByName(e, "REPEATHEAD"))) t->repeathead = atoi(at);
-    if ((at = FindAttValByName(e, "NCOLS")))	  t->ncols	= at;
+    if ((at = FindAttValByName(e, "COLS")))	  t->cols	= at;
 
     /* Set some things for later when processing this table */
     if (set_globals) {
@@ -254,7 +477,7 @@ SetTabAtts(
     }
 
     if (t->frame) {
-	/* top|bottom|topbot|all|sides|none */
+	/* Top|Bottom|Topbot|All|Sides|None */
 	if (!strcmp(t->frame, "NONE") || !strcmp(t->frame, "SIDES"))
 	    frametop = framebot = 0;
 	else if (!strcmp(t->frame, "TOP"))    framebot = 0;
@@ -271,32 +494,14 @@ SetTabAtts(
     /* Now, split (space-separated) strings into vectors.  Hopefully, the
      * number of elements in each vector matches the number of columns.
      */
-    t->halign_v    = Split(t->halign, &t->n_halign, S_STRDUP|S_ALVEC);
-    t->model_v     = Split(t->model, &t->n_model, S_STRDUP|S_ALVEC);
+    t->align_v     = Split(t->align, &t->n_align, S_STRDUP|S_ALVEC);
     t->colwidth_v  = Split(t->colwidth, &t->n_colwidth, S_STRDUP|S_ALVEC);
-    t->colweight_v = Split(t->colweight, &t->n_colweight, S_STRDUP|S_ALVEC);
     t->colsep_v    = Split(t->colsep, &t->n_colsep, S_STRDUP|S_ALVEC);
 
-    /* Determin the _numeric_ number of columns, "nc".  The order in which we
-     * check things to set nc is: NCOLS attribute, # of child element of 1st
-     * row, number of tokens in the various attr lists.
-     */
-    if (t->ncols) t->nc = atoi(t->ncols);
-
-    /* If ncols attribute not set, see how many children first child has.
-     * I can't see how this can be non-zero (unless there are no rows, or
-     * no rows have any cells).
+    /* Determin the _numeric_ number of columns, "nc".  MUST be specified
+     * in Cols attribute of TGroup element.
      */
-    if (!t->nc && e->necont) t->nc = e->econt[0]->necont;
-
-    /* If ncols still not set, guess it from other attrs. Last resort. */
-    if (!t->nc) {
-	if (t->n_halign)   t->nc = t->n_halign;
-	else if (t->n_model)     t->nc = t->n_model;
-	else if (t->n_colwidth)  t->nc = t->n_colwidth;
-	else if (t->n_colweight) t->nc = t->n_colweight;
-	else if (t->n_colsep)    t->nc = t->n_colsep;
-    }
+    if (t->cols) t->nc = atoi(t->cols);
 }
 
 /* ______________________________________________________________________ */
@@ -312,10 +517,8 @@ FreeTabAtts(
 )
 {
     if (!t) return;
-    if (t->halign_v)    free(*t->halign_v);
-    if (t->model_v)     free(*t->model_v);
+    if (t->align_v)     free(*t->align_v);
     if (t->colwidth_v)  free(*t->colwidth_v);
-    if (t->colweight_v) free(*t->colweight_v);
     if (t->colsep_v)    free(*t->colsep_v);
 }
 
@@ -333,19 +536,26 @@ CheckTable(
 {
     int		pr_loc=0;	/* flag to say if we printed location */
     int		i, r, c;
+    Element_t	*ep, *ep2;
     float	wt;
     char	*tpref = "Table Check";		/* prefix for err messages */
     char	*ncolchk =
 	"Table Check: %s ('%s') has wrong number of tokens.  Expecting %d.\n";
 
-    if (strcmp(e->gi, "TABLE")) {
-	fprintf(stderr, "%s: Not pointing to a table!\n", tpref);
+    if (strcmp(e->gi, "TABLE") &&
+	strcmp(e->gi, "INFORMALTABLE") &&
+	strcmp(e->gi, "TGROUP") &&
+	strcmp(e->gi, "COLSPEC") &&
+	strcmp(e->gi, "ROW") ) {
+	fprintf(stderr, "%s: Not pointing to a table element(%s)!\n",
+						tpref, e->gi);
 	return;
     }
 
     FreeTabAtts(&TheTab);	/* free storage, if allocated earlier */
     SetTabAtts(e, &TheTab, 1);	/* look at attributes */
 
+#if FALSE
     /* NCOLS attribute set? */
     if (!TheTab.ncols) {
 	pr_loc++;
@@ -353,34 +563,42 @@ CheckTable(
 		tpref, TheTab.nc);
     }
 
-    /* HALIGN attribute set? */
-    if (!TheTab.halign) {
+    /* ALIGN attribute set? */
+    if (!TheTab.align) {
 	pr_loc++;
-	fprintf(stderr, "%s: HALIGN attribute missing.\n", tpref);
+	fprintf(stderr, "%s: ALIGN attribute missing.\n", tpref);
     }
 
     /* See if the number of cells in each row matches */
-    for (r=0; r<e->necont; r++) {
-	if (e->econt[r]->necont != TheTab.nc) {
-	    pr_loc++;
-	    fprintf(stderr, "%s: NCOLS (%d) differs from actual number of cells (%d) in row %d.\n",
-		tpref, TheTab.nc, e->econt[r]->necont, r);
+    for (r=0; r<e->necont && (ep=e->econt[r]); r++) {	/* each TGroup */
+	for (i=0;  i<ep->necont && (ep2=ep->econt[i]);  i++)	{
+	    if ( strcmp(ep2->gi, "TBODY") )	/* only TBodys */
+		continue;
+
+	    for (c=0;  c<ep2->necont;  c++)	{
+	    	if (ep2->econt[c]->necont != TheTab.nc) {
+		    pr_loc++;
+		    fprintf(stderr, "%s: COLS (%d) differs from actual number of cells (%d) in row %d.\n",
+				tpref, TheTab.nc, ep2->econt[c]->necont, c);
+		}
+	    }
 	}
     }
+#endif
 
-    /* Check HALIGN */
-    if (TheTab.halign) {
-	if (TheTab.nc != TheTab.n_halign) {	/* number of tokens OK? */
+    /* Check ALIGN */
+    if (TheTab.align) {
+	if (TheTab.nc != TheTab.n_align) {	/* number of tokens OK? */
 	    pr_loc++;
-	    fprintf(stderr, ncolchk, "HALIGN", TheTab.halign, TheTab.nc);
+	    fprintf(stderr, ncolchk, "ALIGN", TheTab.align, TheTab.nc);
 	}
 	else {				/* values OK? */
 	    for (i=0; i<TheTab.nc; i++) {
-		if (*TheTab.halign_v[i] != 'c' && *TheTab.halign_v[i] != 'l' &&
-			*TheTab.halign_v[i] != 'r') {
+		if (*TheTab.align_v[i] != 'C' && *TheTab.align_v[i] != 'L' &&
+			*TheTab.align_v[i] != 'R') {
 		    pr_loc++;
-		    fprintf(stderr, "%s: HALIGN (%d) value wrong: %s\n",
-			tpref, i, TheTab.halign_v[i]);
+		    fprintf(stderr, "%s: ALIGN (%d) value wrong: %s\n",
+			tpref, i, TheTab.align_v[i]);
 		}
 	    }
 	}
@@ -402,24 +620,6 @@ CheckTable(
 	}
     }
 
-    /* check COLWEIGHT */
-    if (TheTab.colweight) {
-	if (TheTab.nc != TheTab.n_colweight) {	/* number of tokens OK? */
-	    pr_loc++;
-	    fprintf(stderr, ncolchk, "COLWEIGHT", TheTab.colweight, TheTab.nc);
-	}
-	else {				/* values OK? */
-	    for (i=0; i<TheTab.nc; i++) {	/* check that magitude is reasonable */
-		wt = atof(TheTab.colweight_v[i]);
-		if (wt > 50.0) {
-		    pr_loc++;
-		    fprintf(stderr, "%s: unreasonable COLWEIGHT value: %f.\n",
-				tpref, wt);
-		}
-	    }
-	}
-    }
-
     /* check COLSEP */
     if (TheTab.colsep) {
 	if (TheTab.nc != TheTab.n_colsep) {	/* number of tokens OK? */
@@ -432,30 +632,6 @@ CheckTable(
 	}
     }
 
-    /* See if MODEL has the same number of tokens as NCOLS.  Then do model. */
-    if (TheTab.model) {
-	if (TheTab.nc != TheTab.n_model) {
-	    pr_loc++;
-	    fprintf(stderr, ncolchk, "MODEL", TheTab.model, TheTab.nc);
-	}
-
-	for (r=0; r<e->necont; r++) {
-	    /* only check normal rows */
-	    if (strcmp(e->econt[r]->gi, "ROW")) continue;
-	    for (c=0; c<e->econt[r]->necont; c++) {
-		if (!strcmp(TheTab.model_v[c], "text") ||
-			!strcmp(TheTab.model_v[c], "-")) continue;
-		if (e->econt[r]->econt[c]->necont &&
-		    strcmp(e->econt[r]->econt[c]->econt[0]->gi, TheTab.model_v[c])) {
-		    fprintf(stderr, "%s: MODEL wants %s, but cell contains %s: row %d, cell %d.\n",
-			tpref, TheTab.model_v[c],
-			e->econt[r]->econt[c]->econt[0]->gi, r, c);
-		    pr_loc++;
-		}
-	    }
-	}
-    }
-
     if (pr_loc) {
 	fprintf(stderr, "%s: Above problem in table located at:\n", tpref);
 	PrintLocation(e, stderr);
@@ -463,144 +639,8 @@ CheckTable(
 }
 
 /* ______________________________________________________________________ */
-/*  Do the "right thing" for the table spec for tbl (troff) tables.  This will
- *  generate the "center,box,tab(@)..." and the column justification stuff.
- *  Arguments:
- *	Pointer to element (table) under consideration.
- *	FILE pointer to where to write output.
- */
-void
-TblTable(
-    Element_t	*e,
-    FILE	*fp
-)
-{
-    int		i, n;
-    char	*fr;
-    float	tot;
-    char	*cp, wbuf[1500], **widths=0, **widths_v=0, *mp;
-
-    FreeTabAtts(&TheTab);	/* free storage, if allocated earlier */
-    SetTabAtts(e, &TheTab, 1);	/* look at attributes */
-
-    fr = "box";				/* default framing */
-    frameall = 1;
-    siderules = 0;
-    if (TheTab.frame) {
-	if (!strcmp(TheTab.frame, "ALL")) {
-	    fr = "box";
-	    frametop = framebot = 0;
-	}
-	else {
-	    fr = "";
-	    frameall = 0;
-	}
-	if (!strcmp(TheTab.frame, "SIDES")) siderules = 1;
-    }
-    else frametop = framebot = 0;	/* because 'box' is default */
-    fprintf(fp, "center, %s%s tab(@);\n", fr, ((*fr)?",":""));
-
-    /* Figure out the widths, based either on "colwidth" or "colweight".
-     * (we pick width over weight if both are specified). */
-    if (TheTab.colwidth && TheTab.nc == TheTab.n_colwidth) {
-	widths = TheTab.colwidth_v;
-    }
-    else if (TheTab.colweight && TheTab.nc == TheTab.n_colweight) {
-	for (n=0,i=0; i<TheTab.nc; i++) n += atoi(TheTab.colweight_v[i]);
-	tot = (float)n;
-	cp = wbuf;
-	for (i=0; i<TheTab.nc; i++) {
-	    sprintf(cp, "%5.3fin", atof(TheTab.colweight_v[i])*(TEXTWIDTH/tot));
-	    while (*cp) cp++;
-	    *cp++ = ' ';
-	}
-	*cp = EOS;
-	widths_v = Split(wbuf, 0, S_ALVEC);
-	widths = widths_v;
-    }
-
-    /* Remember the base model in case we do spans later.  We write it
-     * into a static buffer, then output it at once. */
-    mp = basemodel;
-    if (siderules) *mp++ = '|';
-    for (i=0; i<TheTab.nc; i++) {
-	/* If width specified, use it; else if halign set, use it; else left. */
-	if (widths && widths[i][0] != '0' && widths[i][1] != EOS) {
-	    if (i) *mp++ = ' ';
-	    strcpy(mp, TheTab.halign_v[i]);
-	    while (*mp) mp++;
-	    *mp++ = 'w';
-	    *mp++ = '(';
-	    strcpy(mp, widths[i]);
-	    while (*mp) mp++;
-	    *mp++ = ')';
-	}
-	else if (TheTab.halign && TheTab.nc == TheTab.n_halign) {
-	    if (i) *mp++ = ' ';
-	    strcpy(mp, TheTab.halign_v[i]);
-	    while (*mp) mp++;
-	}
-	else {
-	    if (i) *mp++ = ' ';
-	    *mp++ = 'l';
-	}
-	/* See if we want column separators. */
-
-	if (TheTab.colsep) {
-	    if ( (i+1) < TheTab.nc ) {
-		if ( *TheTab.colsep_v[i] == '1' )
-		    *mp++ = '|';
-		if ( *TheTab.colsep_v[i] == '2') {
-		    *mp++ = '|';
-		    *mp++ = '|';
-		}
-	    }
-	}
-    }
-    if (siderules) *mp++ = '|';
-/*    *mp++ = '.';*/
-/*    *mp++ = '^';*/
-    *mp = EOS;
-    OutputString(basemodel, fp, 1);
-    OutputString(".^", fp, 1);
-
-    if (widths_v) free(widths_v);
-}
-
-/*
- *  Arguments:
- *	Pointer to element (cell) under consideration.
- *	FILE pointer to where to write output.
- */
-void
-TblTableCellStart(
-    Element_t	*e,
-    FILE	*fp
-)
-{
-    /* nothing to do at start of cell */
-}
-
-/*
- *  Arguments:
- *	Pointer to element (cell) under consideration.
- *	FILE pointer to where to write output.
- */
-void
-TblTableCellEnd(
-    Element_t	*e,
-    FILE	*fp
-)
-{
-    /* do cell/col separators */
-    if (e->my_eorder < (TheTab.nc-1)) {
-	if (spaninfo[e->my_eorder] == SPAN_NOT ||
-			spaninfo[e->my_eorder+1] != SPAN_CONT)
-	    OutputString("@", fp, 1);
-    }
-}
 
-/*  Look at model attribute for spanning.  If set, remember info for when
+/*  Look at colspec attribute for spanning.  If set, remember info for when
  *  doing the cells.  Called by TblTableRowStart() and TexTableRowStart().
  *  Arguments:
  *	Pointer to element (row) under consideration.
@@ -614,7 +654,14 @@ check_for_spans(
     char	**spans;
     int		n, i, inspan;
 
-    /* See if MODEL attr is set */
+#if FALSE	/* NOT IMPLEMENTED RIGHT NOW */
+
+    /* See if COLSPEC element present */
+    for (i=0;  i < e->necont;  i++)	{
+	
+    }
+
+
     if ((at = FindAttValByName(e, "MODEL"))) {
 
 	/* Split into tokens, then look at each for the word "span" */
@@ -642,150 +689,11 @@ check_for_spans(
     }
     /* if model not set, mark all as not spanning */
     else
-	for (i=0; i<MAXCOLS; i++) spaninfo[i] = SPAN_NOT;
-    return 0;
-}
-
-/*  Output format for cell.  Called from TblTableRowStart().
- *  Arguments:
- *	Pointer to table info structure (for this row)
- *	Which cell/column we're considering
- *	Flag saying whether we're on last column
- *	Default format of col, if none is set for this row or table
- *	FILE pointer to where to write output.
- */
-
-void
-tbl_cell_fmt(
-    TableInfo	*t,
-    int 	i,
-    int		lastcol,
-    char	*def_fmt,
-    FILE	*fp
-)
-{
-    if (t->halign) OutputString(t->halign_v[i], fp, 1);
-    else if (TheTab.halign) OutputString(TheTab.halign_v[i], fp, 1);
-    else OutputString(def_fmt, fp, 1);
-
-    if (!lastcol && spaninfo[i+1] != SPAN_CONT) {
-	if (t->colsep) {
-	    if (*t->colsep_v[i] == '1')
-		OutputString("|", fp, 1);
-	    if (*t->colsep_v[i] == '2')
-		OutputString("||", fp, 1);
-	}
-	else if (TheTab.colsep) {
-	    if (*TheTab.colsep_v[i] == '1')
-		OutputString("|", fp, 1);
-	    if (*TheTab.colsep_v[i] == '2')
-		OutputString("||", fp, 1);
-	}
-	else OutputString("|", fp, 1);
-    }
-    OutputString(" ", fp, 1);
-}
-
-/*  
- *  Arguments:
- *	Pointer to element (row) under consideration.
- *	FILE pointer to where to write output.
- */
-
-void
-TblTableRowStart(
-    Element_t	*e,
-    FILE	*fp
-)
-{
-    int		i, lastcol, stayhere;
-    char	**basev, *cp;
-    TableInfo	RowInfo;
-
-    /* check if we're spanning, or if HALIGN set */
-    stayhere = 0;
-    if (check_for_spans(e)) stayhere = 1;
-    SetTabAtts(e, &RowInfo, 0);
-    if (RowInfo.halign) stayhere = 1;
-
-    if (!stayhere) return;
-
-    /* Change table layout because we have a span, or the row has HALIGN. */
-    OutputString("^.T&^", fp, 1);
-    basev = Split(basemodel, 0, S_ALVEC|S_STRDUP);
-
-    for (i=0; i<TheTab.nc; i++) {
-
-	lastcol = !(i < TheTab.nc-1);
-	if (spaninfo[i] == SPAN_START) {
-	    tbl_cell_fmt(&RowInfo, i, lastcol, "c ", fp);
-	}
-	else if (spaninfo[i] == SPAN_CONT) {
-	    /* See if next col is NOT spanned, and we're not in last col */
-	    OutputString("s", fp, 1);
-	    if (!lastcol && spaninfo[i+1] != SPAN_CONT) {
-		if (RowInfo.colsep) cp = RowInfo.colsep_v[i];
-		else if (TheTab.colsep) cp = TheTab.colsep_v[i];
-		else cp = "1";
-
-		if (*cp == '1')
-		    OutputString("|", fp, 1);
-		if (*cp == '2')
-		    OutputString("||", fp, 1);
-	    }
-	    OutputString(" ", fp, 1);
-	}
-	else
-	    tbl_cell_fmt(&RowInfo, i, lastcol, "l ", fp);
-    }
-    OutputString("^", fp, 1);
-    OutputString(basemodel, fp, 1);
-    OutputString(".^", fp, 1);
-    free(*basev);
-    free(basev);
-    FreeTabAtts(&RowInfo);
-}
-
-/*
- *  Arguments:
- *	Pointer to element (row) under consideration.
- *	FILE pointer to where to write output.
- */
-void
-TblTableRowEnd(
-    Element_t	*e,
-    FILE	*fp
-)
-{
-    char	*at;
-
-    /* See if we're on the last row, then if we're putting a frame
-     * around the whole table.  If so, we need no bottom separator. */
-    if ((e->parent->necont-1) == e->my_eorder) {
-	if (frameall || framebot) return;
-    }
-    /* check this row's attributes */
-    if ((at = FindAttValByName(e, "ROWSEP"))) {
-	if (at[0] == '1') fprintf(fp, "_\n");
-    }
-    else if (rowsep) /* fprintf(fp, "_\n") */ ;
-}
 
-/*
- *  Arguments:
- *	Pointer to element (table) under consideration.
- *	FILE pointer to where to write output.
- */
-void
-TblTableTop(Element_t *e, FILE *fp)
-{
-    if (frametop) OutputString("^_^", fp, 1);
-}
+#endif	/* NOT CURRENTLY IMPLEMENTED */
 
-void
-TblTableBottom(Element_t *e, FILE *fp)
-{
-    if (framebot) OutputString("^_^", fp, 1);
+	for (i=0; i<MAXCOLS; i++) spaninfo[i] = SPAN_NOT;
+    return 0;
 }
 
 /* ______________________________________________________________________ */
@@ -807,25 +715,14 @@ TexTable(
 
     FreeTabAtts(&TheTab);	/* free storage, if allocated earlier */
     SetTabAtts(e, &TheTab, 1);	/* look at attributes */
+    SetTabAtts(e->econt[0], &TheTab, 1);	/* attrs of TGroup */
 
-    /* Figure out the widths, based either on "colwidth" or "colweight".
-     * (we pick width over weight if both are specified). */
+    /* Figure out the widths, based either on "colwidth".
+     */
     if (TheTab.colwidth && TheTab.nc == TheTab.n_colwidth) {
 	widths = TheTab.colwidth_v;
     }
-    else if (TheTab.colweight && TheTab.nc == TheTab.n_colweight) {
-	for (n=0,i=0; i<TheTab.nc; i++) n += atoi(TheTab.colweight_v[i]);
-	tot = (float)n;
-	cp = wbuf;
-	for (i=0; i<TheTab.nc; i++) {
-	    sprintf(cp, "%5.3fin", atof(TheTab.colweight_v[i])*(TEXTWIDTH/tot));
-	    while (*cp) cp++;
-	    *cp++ = ' ';
-	}
-	*cp = EOS;
-	widths_v = Split(wbuf, 0, S_ALVEC);
-	widths = widths_v;
-    }
+
     siderules = 1;
     if (TheTab.frame)
 	if (strcmp(TheTab.frame, "ALL") && strcmp(TheTab.frame, "SIDES"))
@@ -833,12 +730,12 @@ TexTable(
 
     if (siderules) OutputString("|", fp, 1);
     for (i=0; i<TheTab.nc; i++) {
-	/* If width specified, use it; else if halign set, use it; else left. */
+	/* If width specified, use it; else if align set, use it; else left. */
 	if (widths && widths[i][0] != '0' && widths[i][1] != EOS) {
 	    fprintf(fp, "%sp{%s}", (i?" ":""), widths[i]);
 	}
-	else if (TheTab.halign && TheTab.nc == TheTab.n_halign) {
-	    fprintf(fp, "%s%s", (i?" ":""), TheTab.halign_v[i]);
+	else if (TheTab.align && TheTab.nc == TheTab.n_align) {
+	    fprintf(fp, "%s%s", (i?" ":""), TheTab.align_v[i]);
 	}
 	else
 	    fprintf(fp, "%sl", (i?" ":""));
@@ -885,7 +782,7 @@ TexTableCellStart(
 	OutputString(buf, fp, 1);
     }
 #ifdef New
-    if ((at = FindAttValByName(e->parent, "HALIGN"))) {
+    if ((at = FindAttValByName(e->parent, "ALIGN"))) {
 	/* no span, but user wants to change the alignment */
 	h_v = Split(wbuf, 0, S_ALVEC|S_STRDUP);
 	OutputString("\\\\multicolumn{1}{%sc%s}", n,
@@ -970,6 +867,1176 @@ TexTableBottom(Element_t *e, FILE *fp)
 {
     if (framebot) OutputString("\\\\hline", fp, 1);
 }
-
+
+/* ______________________________________________________________________ */
+/* ______________________________________________________________________ */
+/* ______________________________________________________________________ */
 /* ______________________________________________________________________ */
+/* ______________________________________________________________________ */
+/* ___________________________|             |____________________________ */
+/* ___________________________|  TBL STUFF  |____________________________ */
+/* ___________________________|             |____________________________ */
+/* ___________________________|_____________|____________________________ */
+/* ______________________________________________________________________ */
+/* ______________________________________________________________________ */
+/* ______________________________________________________________________ */
+/* ______________________________________________________________________ */
+
+
+
+/*	TblTStart()  --  start a table and do style information
+ *
+ *  TO DO:
+ *
+ *	do .TS
+ *	find global rowsep and colsep
+ */
+
+
+void
+TblTStart(Element_t * ep,
+	  FILE * fP)
+{
+	char * cp;
+	struct Element_t * ep2;
+
 
+
+	OutputString("^.TS^", fP, 1);
+
+	tblTGroupSeen = FALSE;
+	tblinBOFT = FALSE;	/* within a boft? */
+	tblBOFTCount = 0;	/* count of Blocks of Filled Text that
+				 * we've created */
+
+	tblgcolsep = (cp = FindAttValByName(ep, "COLSEP")) && !strcmp(cp, "1");
+	tblgrowsep = (cp = FindAttValByName(ep, "ROWSEP")) && !strcmp(cp, "1");
+}
+
+/*      TblTEnd()  --  end a table and do any cleanup
+ *
+ *  TO DO:
+ *
+ *	do .TE
+ *
+ *	deallocate format line info
+ */
+
+
+
+void
+TblTEnd(Element_t * ep,
+	FILE * fP)
+{
+	struct tblformat * ffp, * ffp2;
+
+
+	if ( tblBOFTCount > 31 )	{
+		fprintf(stderr, "# warning, line %d: created %d blocks of filled text in one table\n",
+					ep->lineno, tblBOFTCount);
+		fprintf(stderr, "#\t\t(31 is the limit in some systems)\n");
+	}
+
+	OutputString("^.TE^", fP, 1);
+
+	for ( ffp=formP;  ffp;  ffp=ffp2 )	{
+		ffp2 = ffp->next;
+		free(ffp);		/* clear entire list */
+	}
+	formP = 0;
+}
+
+/*      TblTTGroup()  --  do body work (row format info)
+ *
+ *  TO DO:
+ *
+ *	set number of columns
+ *
+ *	if this is the first TGroup of this table, do style info:
+ *	   a. alignment
+ *	   b. defaults:  tab
+ *	   c. box vx allbox
+ *
+ *	do format info:
+ *	   a. generate tableformat structure
+ *	   b. output it
+ *
+ *	prepare structures for colspecs and spanspecs
+ *
+ */
+
+
+
+void
+TblTGroup(Element_t * ep,
+	  FILE * fP)
+{
+	int i, j, k;
+	char * cp, * cp2;
+	Element_t * ep2, ep3;
+	struct tblcolspec * tcsp, * tcsp2;
+	struct tblspanspec * tssp, * tssp2;
+
+
+	tblColSpec = 0;		/* make sure they're clear */
+	tblSpanSpec = 0;
+
+    /* set the number of columns */
+
+    	tblcols = atoi(FindAttValByName(ep, "COLS"));
+
+    /* do colspecs */
+
+    	tblColSpec = tcsp = TblDoColSpec(0, ep, 0, TGroup);
+    			/* do TGroup first -- it becomes the default */
+
+	for ( i=0, k=1;  i < ep->necont;  i++ )	{
+
+		if ( !strcmp(ep->econt[i]->gi, "COLSPEC") )	{
+			tcsp2 = TblDoColSpec(k, ep->econt[i], tblColSpec, TGroup);
+			tcsp->next = tcsp2;	/* put into list */
+			tcsp = tcsp2;
+			k = tcsp2->num + 1;	/* next column number */
+		}
+
+		if ( !strcmp(ep->econt[i]->gi, "THEAD") )	{
+			ep2 = ep->econt[i];
+			for ( j=0, k=1;  j < ep2->necont;  j++ )	{
+				if ( !strcmp(ep2->econt[j]->gi, "COLSPEC") )	{
+					tcsp2 = TblDoColSpec(k, ep2->econt[j], tblColSpec, THead);
+					tcsp->next = tcsp2;	/* put into list */
+					tcsp = tcsp2;
+					k = tcsp2->num + 1;	/* next column number */
+				}
+			}
+		}
+
+		if ( !strcmp(ep->econt[i]->gi, "TFOOT") )	{
+			ep2 = ep->econt[i];
+			for ( j=0, k=1;  j < ep2->necont;  j++ )	{
+				if ( !strcmp(ep2->econt[j]->gi, "COLSPEC") )	{
+					tcsp2 = TblDoColSpec(k, ep2->econt[j], tblColSpec, TFoot);
+					tcsp->next = tcsp2;	/* put into list */
+					tcsp = tcsp2;
+					k = tcsp2->num + 1;	/* next column number */
+				}
+			}
+		}
+
+		if ( !strcmp(ep->econt[i]->gi, "TBODY") )	{
+			ep2 = ep->econt[i];
+			for ( j=0, k=1;  j < ep2->necont;  j++ )	{
+				if ( !strcmp(ep2->econt[j]->gi, "COLSPEC") )	{
+					tcsp2 = TblDoColSpec(k, ep2->econt[j], tblColSpec, TBody);
+					tcsp->next = tcsp2;	/* put into list */
+					tcsp = tcsp2;
+					k = tcsp2->num + 1;	/* next column number */
+				}
+			}
+		}
+	}
+
+    /* do spanspecs */
+
+	tblSpanSpec = tssp = TblDoSpanSpec(ep, 0, TGroup);
+			/* do TGroup first -- it becomes the default */
+
+	for ( i=0;  i < ep->necont;  i++ )	{
+		if ( !strcmp(ep->econt[i]->gi, "SPANSPEC") )	{
+			tssp2 = TblDoSpanSpec(ep->econt[i], tblSpanSpec, TGroup);
+			tssp->next = tssp2;	/* put into list */
+			tssp = tssp2;
+		}
+	}
+
+
+    /* if this is the first TGroup in this table, do style stuff */
+
+	if ( ! tblTGroupSeen )	{
+
+		OutputString("tab(\007)", fP, 1);
+
+		ep2 = ep->parent;
+		if ( ! (tblFrame = FindAttValByName(ep2, "FRAME")) )
+			tblFrame = "";
+
+		if ( !strcmp(tblFrame, "ALL") )	{
+			if ( tcsp->colsep && tcsp->rowsep )
+				OutputString(" allbox", fP, 1);
+			else
+				OutputString(" box", fP, 1);
+		}
+
+		if ( (cp = FindAttValByName(ep, "ALIGN")) &&
+		     !strcmp(cp, "CENTER") )	{
+		     	OutputString(" center", fP, 1);
+		}
+
+		OutputString(";\n", fP, 1);
+		
+		tblTGroupSeen = TRUE;
+	}
+
+
+    /* do format stuff -- step through all THead rows then all TBody
+     * rows.  Build a list of tblformats that describe all of them.
+     * then output the resulting list.
+     */
+
+    	for ( i=0;  i < ep->necont;  i++ )	{
+		if ( !strcmp(ep->econt[i]->gi, "THEAD") )	{
+			TblBuildFormat(ep->econt[i], &formP, THead);
+						/* add in those rows */
+			break;
+    		}
+    	}
+
+    	for ( i=0;  i < ep->necont;  i++ )	{
+		if ( !strcmp(ep->econt[i]->gi, "TBODY") )	{
+			TblBuildFormat(ep->econt[i], &formP, TBody);
+						/* add in those rows */
+			break;
+    		}
+    	}
+
+	TblPrintFormat(fP, formP);
+
+	tblrow = 0;		/* the current row within this format */
+}
+
+/*      TblTGroupEnd()  --  end a TGroup
+ *
+ *  TO DO:
+ *
+ *	deallocate colspecs and spanspecs
+ */
+
+
+void
+TblTGroupEnd(Element_t * ep,
+	      FILE * fP)
+{
+	struct tblcolspec * tcsp, * tcsp2;
+	struct tblspanspec * tssp, * tssp2;
+
+
+	for ( tcsp=tblColSpec;  tcsp;  tcsp=tcsp2 )	{
+		tcsp2 = tcsp->next;
+		free(tcsp);
+	}
+	for ( tssp=tblSpanSpec;  tssp;  tssp=tssp2 )	{
+		tssp2 = tssp->next;
+		free(tssp);
+	}
+}
+
+/*      TblTTFoot()  --  do body foot work (row format info)
+ *
+ *  TO DO:
+ *
+ *	do format info:
+ *	   a. generate tableformat structure
+ *	      i. if it is only 1 line long and matches the
+ *		 prevailing format, just output rows.
+ *	     ii. else, output a .T& and the new format specs
+ */
+
+
+
+void
+TblTFoot(Element_t * ep,
+	 FILE * fP)
+{
+	struct tblformat * ffp, * ffp2;
+	static struct tblformat * tfp, * tfp2;
+
+
+	TblBuildFormat(ep, &tfp, TFoot);	/* gen format for the foot */
+
+	for ( tfp2=formP;  tfp2 && tfp2->next;  tfp2=tfp2->next )
+		;
+
+	if ( tfp->next || !TblFormatMatch(tfp, tfp2) )	{
+
+		for ( ffp=formP;  ffp;  ffp=ffp2 )	{
+			ffp2 = ffp->next;
+			free(ffp);		/* clear entire list */
+		}
+
+		formP = tfp;	/* this becomes the prevailing format */
+
+		OutputString("^.T&^", fP, 1);
+		TblPrintFormat(fP, formP);
+	}
+
+	tblrow = 0;		/* the current row within this format */
+}
+
+/*	TblBuildFormat()  --  build a format structure out of a set of
+ *				rows and columns
+ *
+ */
+
+
+void
+TblBuildFormat(Element_t * ep,		/* parent of rows.. */
+	       struct tblformat ** fp,	/* pointer to head of struct we're
+	       				 * building */
+	       tblsource source)	/* type of record */
+{
+	int i;
+	struct tblformat * lfp; /* "current" format */
+	struct tblformat * nfp; /* the next format */
+
+
+	for ( lfp= *fp;  lfp && lfp->next;  lfp=lfp->next )
+		;			/* find end of format list */
+
+    	for ( i=0;  i < ep->necont;  i++ )
+		if ( !strcmp(ep->econt[i]->gi, "ROW") )
+			break;		/* find where rows start */
+
+	for (  ;  i < ep->necont;  i++ )	{
+
+		nfp = TblBuild1Format(ep->econt[i], FALSE, source);
+						/* do one row */
+
+		if ( !lfp )
+			lfp = *fp = nfp;	/* first one */
+		else
+		if ( TblFormatMatch(lfp, nfp) )
+			lfp->count++;		/* matches */
+		else	{
+			lfp->count = 1;		/* only 1 so far */
+			lfp->next = nfp;	/* new one */
+			lfp = nfp;
+		}
+	}
+}
+
+/*	TblBuild1Format()  --  build one row's worth of format information
+ *
+ */
+
+
+
+struct tblformat *
+TblBuild1Format(Element_t * rp,		/* the row to deal with */
+		bool addinRowsep,	/* insert rowsep into model? */
+		tblsource source)	/* type type of row */
+{
+	int i;
+	bool allProp;
+	float totalProp;
+	struct tblformat * tfp;
+	Element_t * ep;	/* entry pointer */
+
+
+	Calloc(1, tfp, struct tblformat);
+	tfp->cols = tblcols;
+	ep = (rp->necont) ? rp->econt[0] : 0;	/* first entry */
+	allProp = TRUE;
+	totalProp = 0;
+
+	for ( i=1;  i <= tblcols;  i++ )	{
+		tfp->colformat[i] = TblGetAlign(i, ep, source);
+		strcpy(tfp->colwidth[i], TblGetWidth(i, ep, TRUE, source));
+		strcpy(tfp->colpwidth[i], TblGetWidth(i, ep, FALSE, source));
+		if ( allProp )	{
+			allProp = tfp->colpwidth[i][0];
+			totalProp += atof(tfp->colpwidth[i]);
+		}
+		strcpy(tfp->font[i], TblGetFont(i, ep, source));
+		tfp->colsep[i] = tblgcolsep || TblGetColSep(i, ep, source);
+		if ( addinRowsep )
+			tfp->rowsep[i] = tblgrowsep || TblGetRowSep(i, ep, source);
+		tfp->moreRows[i] = TblGetMoreRows(i, ep, source);
+
+		if ( (i < rp->necont) && TblColAdv(i, ep, tfp, source) )	{
+			ep = rp->econt[i];
+		}
+	}
+
+    /* turn proportional widths into real widths */
+
+    	if ( allProp )	{
+    		for ( i=1;  i <= tblcols;  i++ )	{
+    			sprintf(tfp->colwidth[i], "%fi",
+    				(atof(tfp->colpwidth[i]) / totalProp) * TEXTWIDTH);
+    		}
+    	}
+
+	return tfp;
+}
+
+/*	TblGetAlign()  --  get alignment spec for a entry
+ *
+ */
+
+
+char
+TblGetAlign(short col,			/* column number */
+	    Element_t * entry,		/* the entry */
+	    tblsource	source)		/* context */
+{
+	struct tblcolspec * tcsp;
+	struct tblspanspec * tssp;
+	tblalign talign;
+
+
+	if ( entry && (tssp = TblEntrySpanSpec(col, entry, source)) )	{
+		talign = tssp->align;
+		free(tssp);
+	} else
+	if ( entry && (tcsp = TblEntryColSpec(col, entry, source)) )	{
+		talign = tcsp->align;
+		free(tcsp);
+	} else	{
+		return 'l';
+	}
+
+	switch ( talign )	{
+	case Left:	return 'l';
+	case Right:	return 'r';
+	case Center:	return 'c';
+	case Justify:	return 'l';
+	case Char:	return 'd';
+	case Span:	return 's';
+	}
+}
+
+/*	TblGetWidth()  --  get width spec, if any, for a entry
+ *
+ */
+
+
+char *
+TblGetWidth(short col,			/* column number */
+	    Element_t * entry,		/* the entry */
+	    bool	literal,	/* literal (or proportional) */
+	    tblsource	source)		/* context */
+{
+	struct tblcolspec * tcsp;
+	struct tblspanspec * tssp;
+	static char colWidth[10];
+
+
+	colWidth[0] = 0;
+
+	if ( entry &&
+	     (tcsp = TblEntryColSpec(col, entry, source)) &&
+	     tcsp->colwidth[0] )	{
+
+		if ( !strstr(tcsp->colwidth, "*") )	{
+			if ( literal )
+				strcpy(colWidth, tcsp->colwidth);
+		} else	{
+			if ( ! literal )
+				strcpy(colWidth, tcsp->colwidth);
+		}
+		free(tcsp);
+	}
+
+	return colWidth;
+}
+
+/*	TblGetFont()  --  get font spec, if any, for a entry
+ *
+ */
+
+
+char *
+TblGetFont(short col,			/* column number */
+	   Element_t * entry,		/* the entry */
+	   tblsource source)		/* context */
+{
+	struct tblcolspec * tcsp;
+	struct tblspanspec * tssp;
+
+
+	return "";
+}
+
+/*	TblGetColSep()  --  get column separater spec, if any, for a entry
+ *
+ */
+
+
+bool
+TblGetColSep(short col,			/* column number */
+	     Element_t * entry,		/* the entry */
+	     tblsource	source)		/* context */
+{
+	struct tblcolspec * tcsp;
+	struct tblspanspec * tssp;
+	bool colsep;
+
+
+	if ( entry && (tssp = TblEntrySpanSpec(col, entry, source)) )	{
+		colsep = tssp->colsep;
+		free(tssp);
+	} else
+	if ( entry && (tcsp = TblEntryColSpec(col, entry, source)) )	{
+		colsep = tcsp->colsep;
+		free(tcsp);
+	} else
+		colsep = FALSE;
+
+	return colsep;
+}
+
+/*	TblGetRowSep()  --  get row separater spec, if any, for a entry
+ *
+ */
+
+
+bool
+TblGetRowSep(short col,			/* column number */
+	     Element_t * entry,		/* the entry */
+	     tblsource	source)		/* context */
+{
+	struct tblcolspec * tcsp;
+	struct tblspanspec * tssp;
+	bool rowsep;
+
+	if ( entry && (tssp = TblEntrySpanSpec(col, entry, source)) )	{
+		rowsep = tssp->rowsep;
+		free(tssp);
+	} else
+	if ( entry && (tcsp = TblEntryColSpec(col, entry, source)) )	{
+		rowsep = tcsp->rowsep;
+		free(tcsp);
+	} else	{
+		rowsep = FALSE;
+	}
+
+	return rowsep;
+}
+
+/*	TblGetmoreRows()  --  get moreRows value
+ *
+ */
+
+
+bool
+TblGetMoreRows(short col,		/* column number */
+	       Element_t * entry,	/* the entry */
+	       tblsource	source)	/* context */
+{
+	char * cp;
+
+
+	if ( cp = FindAttValByName(entry, "MOREROWS") )
+		return atoi(cp);
+	else
+		return 0;
+}
+
+/*	TblColAdv()  --  advance pointer to next entry, if appropriate
+ *
+ */
+
+
+bool
+TblColAdv(short col,		/* the current column */
+	  Element_t *ep,	/* pointer to entry */
+	  struct tblformat * tfp, /* pointer to prevailing format */
+	  tblsource source)	/* context */
+{
+	bool bump;
+	struct tblspanspec * tssp;
+
+
+	bump = TRUE;
+
+	if ( tssp = TblEntrySpanSpec(col, ep, source) )	{
+		bump = tssp->align != Span;
+		free(tssp);
+	}
+
+	return bump;
+}
+
+/*	TblEntryColSpec()  --  get a completely localized colspec for an entry
+ *
+ */
+
+
+struct tblcolspec *
+TblEntryColSpec(short num,		/* column number */
+		Element_t * ep,		/* entry */
+		tblsource source)	/* context */
+{
+	int i;
+	bool throwAway;
+	char * cp;
+	struct tblcolspec * tcsp, * tcsp2;
+
+
+	tcsp = tcsp2 = 0;
+	throwAway = FALSE;
+
+	if ( (cp = FindAttValByName(ep, "COLNAME")) )	{
+		if ( ! (tcsp = TblFindColSpec(cp, source)) )	{
+			fprintf(stderr, "? can't find column name '%s'\n", cp);
+		}
+	}
+
+	if ( tcsp2 = TblFindColNum(num, source) )	{
+		tcsp = TblDoColSpec(num, ep, tcsp2, source);
+		throwAway = TRUE;
+	}
+
+	tcsp2 = TblDoColSpec(num, ep, tcsp, source);
+
+	if ( throwAway )
+		free(tcsp);
+
+	return tcsp2;
+}
+
+/*	TblEntrySpanSpec()  --  get a completely localized spanspec for an entry
+ *
+ */
+
+
+struct tblspanspec *
+TblEntrySpanSpec(short num,		/* column number */
+		 Element_t * ep,	/* entry */
+		 tblsource source)	/* context */
+{
+	char * cp, * cp2;
+	struct tblspanspec * tssp, * tssp2;
+
+
+	tssp2 = 0;
+
+	if ( !(cp = FindAttValByName(ep, "SPANNAME")) ||
+	     !(tssp2 = TblFindSpanSpec(cp, source)) )	{
+
+	     	if ( !FindAttValByName(ep, "NAMEST") )
+	     		return 0;
+	}
+
+	tssp = TblDoSpanSpec(ep, tssp2, source);
+
+	if ( tssp->start && tssp->end &&
+	     (tssp->start->num < num) && (tssp->end->num >= num) )	{
+		tssp->align = Span;
+	}
+
+	return tssp;
+}
+
+/*	TblFormatMatch()  --  compare two format rows for consistency
+ *
+ */
+
+
+bool
+TblFormatMatch(struct tblformat * tf1,	/* one row */
+	       struct tblformat * tf2)	/* the other */
+{
+	int i;
+
+	if ( tf1->cols != tf2->cols )	{
+		return FALSE;
+	}
+
+	for ( i=0;  i < tf1->cols;  i++ )	{
+
+		if ( tf1->colformat[i] != tf2->colformat[i] )	{
+			return FALSE;
+		}
+		if ( strcmp(tf1->colwidth[i], tf2->colwidth[i]) )	{
+			return FALSE;
+		}
+		if ( strcmp(tf1->font[i], tf2->font[i]) )	{
+			return FALSE;
+		}
+		if ( tf1->colsep[i] != tf2->colsep[i] )	{
+			return FALSE;
+		}
+		if ( tf1->rowsep[i] != tf2->rowsep[i] )	{
+			return FALSE;
+		}
+		if ( tf1->moreRows[i] || tf2->moreRows[i] )	{
+			return FALSE;
+		}
+	}
+
+	return TRUE;
+}
+
+/*	TblPrintFormat()  --  print a tbl format structure
+ *
+ */
+
+
+void
+TblPrintFormat(FILE * fP,		/* where to print */
+	       struct tblformat * tfp)	/* the structure */
+{
+	int i;
+	struct tblformat * tfp2, * tfp3;
+	static char buf[3] = "\000\000";
+
+
+	for ( tfp2=tfp, tfp3=0;  tfp2;  tfp2=tfp2->next )	{
+		for ( i=1;  i <= tfp->cols;  i++ )	{
+			if ( i > 1 )
+				OutputString(" ", fP, 1);
+			if ( tfp3 && tfp3->moreRows[i] )
+				OutputString("\\^", fP, 1);
+			else	{
+				buf[0] = tfp2->colformat[i];
+				OutputString(buf, fP, 1);
+			}
+			if ( tfp2->colwidth[i][0] )	{
+				OutputString("w(", fP, 1);
+				OutputString(tfp2->colwidth[i], fP, 1);
+				OutputString(")", fP, 1);
+			}
+			if ( tfp2->font[i][0] )
+				OutputString(tfp2->font[i], fP, 1);
+			if ( tfp2->colsep[i] )
+				OutputString("|", fP, 1);
+		}
+		if ( ! tfp2->next )
+			OutputString(".", fP, 1);
+		OutputString("^", fP, 1);
+		tfp3 = tfp2;
+	}
+}
+
+/*      TblTRowStart()  --  start a row (not much to do)
+ *
+ *  TO DO:
+ *
+ *	nothing..
+ *
+ */
+
+
+
+void
+TblTRowStart(Element_t * ep,
+	     FILE * fP)
+{
+
+    /* nothing to do */
+
+	tblrow++;	/* except note that we're within a new row */
+
+}
+
+/*      TblTRowEnd()  --  end a row
+ *
+ *  TO DO:
+ *
+ *	output a row end character (newline)
+ *	if the current row had a rowsep, then output a "fake" row
+ *	with underlines in the proper place(s).
+ */
+
+
+
+void
+TblTRowEnd(Element_t * ep,
+	   FILE * fP)
+{
+	int i, k;
+	tblsource source;
+	bool startedRow, didSep;
+	struct tblformat * rfp;
+
+
+	OutputString("^", fP, 1);
+
+    /* get the format for this row */
+
+    	if ( !strcmp(ep->parent->gi, "TFoot") )
+    		source = TFoot;
+	else
+    	if ( !strcmp(ep->parent->gi, "THead") )
+		source = THead;
+	else
+		source = TBody;
+
+    	rfp = TblBuild1Format(ep, TRUE, source);
+	startedRow = FALSE;
+	didSep = FALSE;
+
+	for ( i=1;  i <= formP->cols;  i++ )	{
+		if ( rfp->rowsep[i] ||
+		     (didSep && (rfp->colformat[i] == 's')) )	{
+			if ( ! startedRow )	{
+				OutputString("^", fP, 1);
+				for ( k=1;  k < i;  k++ )
+					OutputString("\007", fP, 1);
+				startedRow = TRUE;
+			}
+			OutputString("_\007", fP, 1);
+			didSep = TRUE;
+		} else	{
+		if ( startedRow )
+			OutputString("\007", fP, 1);
+		}
+		didSep = FALSE;
+	}
+	free(rfp);		/* clear that row.. */
+
+	if ( startedRow )
+		OutputString("^", fP, 1);
+}
+
+/*      TblTEntryStart()  --  start an entry (block of filled text if
+ *				appropriate)
+ *
+ *  TO DO:
+ *
+ *	if text length > BOFTTextThresh or there is PI,
+ *	then output "T{\n", else do nothing
+ *
+ */
+
+
+
+void
+TblTCellStart(Element_t * ep,
+	      FILE * fP)
+{
+	int i;
+	Element_t * ep2;
+	bool sawPIorPara;
+
+
+	for ( i=0, sawPIorPara=FALSE;  i < ep->ncont;  i++ )	{
+		if ( (ep->cont[i].type == '?') ||
+		     (i &&
+		      (ep->cont[i].type == '(') &&
+		      !strcmp(ep->cont[i].ch.elem->gi, "PARA")) )	{
+			sawPIorPara = TRUE;
+			break;
+		}
+	}
+
+	if ( sawPIorPara || (TblCountContent(ep) > BOFTTextThresh) )	{
+		tblBOFTCount++;
+		OutputString("T{^", fP, 1);
+		tblinBOFT = TRUE;	/* within a boft now */
+	}
+}
+
+/*	TblCountContent()  --  count all content below the given element
+ *
+ *
+ */
+
+
+
+int
+TblCountContent(Element_t * ep)		/* the element to look under */
+{
+	int i, count;
+	char * cp;
+
+
+	count = 0;
+
+	for ( i=0;  i < ep->ncont;  i++ )	{
+		if ( ep->cont[i].type == '-' )	{
+			for ( cp=ep->cont[i].ch.data; *cp; cp++, count++ )
+				if ( *cp == -1 )
+					return BOFTTextThresh + 1;
+		} else
+		if ( ep->cont[i].type == '(' )	{
+			count += TblCountContent(ep->cont[i].ch.elem);
+		}
+	}
+
+	return count;
+}
+
+/*      TblTEntryEnd()  --  end an entry
+ *
+ *  TO DO:
+ *
+ *	if within BOFT, output "T}"
+ *	if not last entry, output tab character
+ *
+ */
+
+
+
+void
+TblTCellEnd(Element_t * ep,
+	    FILE * fP)
+{
+	Element_t * ep2;
+
+
+	if ( tblinBOFT )	{
+		OutputString("^T}", fP, 1);
+		tblinBOFT = FALSE;	/* back out again */
+	}
+
+	for ( ep2=ep->next;  ep2;  ep2=ep2->next )	{
+		if ( !strcmp(ep2->gi, "ENTRY") || !strcmp(ep2->gi, "ENTRYTBL") )	{
+			OutputString("\007", fP, 1);
+			break;
+		}
+		if ( !strcmp(ep2->gi, "ROW") )
+			break;
+	}
+}
+
+/*	TblDoColSpec()  --  process one element to create a new colspec
+ *
+ *
+ */
+
+
+
+struct tblcolspec *
+TblDoColSpec(short number,		/* this column number */
+	     Element_t * ep,		/* element containing colspec stuff */
+	     struct tblcolspec * pcsp,	/* prevailing colspec (with defaults) */
+	     tblsource source)		/* precedence level of the resulting spec */
+{
+	char * cp;
+	struct tblcolspec * tcsp;
+
+
+	Calloc(1, tcsp, struct tblcolspec);
+
+	if ( cp = FindAttValByName(ep, "COLNAME") )
+		strcpy(tcsp->name, cp);
+
+	tcsp->num = number;
+	tcsp->source = source;
+
+	if ( cp = FindAttValByName(ep, "ALIGN") )	{
+		if      ( !strcmp(cp, "LEFT") )		tcsp->align = Left;
+		else if ( !strcmp(cp, "RIGHT") )	tcsp->align = Right;
+		else if ( !strcmp(cp, "CENTER") )	tcsp->align = Center;
+		else if ( !strcmp(cp, "JUSTIFY") )	tcsp->align = Justify;
+		else if ( !strcmp(cp, "CHAR") )		tcsp->align = Char;
+	} else
+		tcsp->align = ( pcsp ) ? pcsp->align : Left;
+
+	if ( cp = FindAttValByName(ep, "CHAR") )
+		tcsp->alignchar = cp[0];
+	else
+		tcsp->alignchar = ( pcsp ) ? pcsp->alignchar : 0;
+
+	if ( cp = FindAttValByName(ep, "CHAROFF") )
+		tcsp->aligncharoff = atoi(cp);
+	else
+		tcsp->aligncharoff = ( pcsp ) ? pcsp->aligncharoff : 0;
+
+	if ( cp = FindAttValByName(ep, "COLWIDTH") )
+		snprintf(tcsp->colwidth, sizeof(tcsp->colwidth), "%s", cp);
+	else
+		snprintf(tcsp->colwidth, sizeof(tcsp->colwidth), "%s", ( pcsp ) ? pcsp->colwidth : "");
+
+	if ( cp = FindAttValByName(ep, "COLSEP") )
+		tcsp->colsep = !strcmp(cp, "1");
+	else
+		tcsp->colsep = ( pcsp ) ? pcsp->colsep : FALSE;
+
+	if ( cp = FindAttValByName(ep, "ROWSEP") )
+		tcsp->rowsep = !strcmp(cp, "1");
+	else
+		tcsp->rowsep = ( pcsp ) ? pcsp->rowsep : FALSE;
+
+	return tcsp;
+}
+
+/*	TblDoSpanSpec()  --  process one element to create a new spanspec
+ *
+ *	Note that there's a hack inside here...  NameSt and NameEnd are
+ *	supposed to point at colnames, but if no colname is found, this
+ *	code will look for a colnum by the same value.
+ */
+
+
+
+struct tblspanspec *
+TblDoSpanSpec(Element_t * ep,		/* element containing spanspec stuff */
+	      struct tblspanspec * pssp, /* prevailing spanspec (with defaults) */
+	      tblsource source)		/* precedence level of the resulting spec */
+{
+	char * cp;
+	struct tblspanspec * tssp;
+	struct tblcolspec * tcsp;
+
+
+	Calloc(1, tssp, struct tblspanspec);
+
+	if ( cp = FindAttValByName(ep, "SPANNAME") ) {
+		snprintf(tssp->name, sizeof(tssp->name), "%s", cp);
+	}
+	tssp->source = source;
+
+	if ( cp = FindAttValByName(ep, "NAMEST") )	{
+		if ( (tcsp = TblFindColSpec(cp, source)) ||
+		     (tcsp = TblFindColNum(atoi(cp), source)) )	{
+		     	tssp->start = tcsp;
+		} else	{
+			fprintf(stderr, "? spanspec namest points to unknown column '%s'\n", cp);
+			tssp->start = 0;
+		}
+	} else	{
+		if ( pssp && pssp->start )	{
+			tssp->start = pssp->start;
+		}
+	}
+
+	if ( cp = FindAttValByName(ep, "NAMEEND") )	{
+		if ( (tcsp = TblFindColSpec(cp, source)) ||
+		     (tcsp = TblFindColNum(atoi(cp), source)) )	{
+		     	tssp->end = tcsp;
+		} else	{
+			fprintf(stderr, "? spanspec nameend points to unknown column '%s'\n", cp);
+			tssp->end = 0;
+		}
+	} else	{
+		if ( pssp && pssp->end )	{
+			tssp->end = pssp->end;
+		}
+	}
+
+	if ( cp = FindAttValByName(ep, "ALIGN") )	{
+		if      ( !strcmp(cp, "LEFT") )		tssp->align = Left;
+		else if ( !strcmp(cp, "RIGHT") )	tssp->align = Right;
+		else if ( !strcmp(cp, "CENTER") )	tssp->align = Center;
+		else if ( !strcmp(cp, "JUSTIFY") )	tssp->align = Justify;
+		else if ( !strcmp(cp, "CHAR") )		tssp->align = Char;
+	} else	{
+		if ( pssp )
+			tssp->align = pssp->align;
+	}
+
+	if ( cp = FindAttValByName(ep, "CHAR") )
+		tssp->alignchar = cp[0];
+	else	{
+		if ( pssp )
+			tssp->alignchar = pssp->alignchar;
+	}
+	if ( cp = FindAttValByName(ep, "CHAROFF") )
+		tssp->aligncharoff = atoi(cp);
+	else	{
+		if ( pssp )
+			tssp->alignchar = pssp->alignchar;
+	}
+
+	if ( cp = FindAttValByName(ep, "COLSEP") )
+		tssp->colsep = !strcmp(cp, "1");
+	else	{
+		if ( pssp )
+			tssp->colsep = pssp->colsep;
+	}
+	if ( cp = FindAttValByName(ep, "ROWSEP") )
+		tssp->rowsep = !strcmp(cp, "1");
+	else	{
+		if ( pssp )
+			tssp->rowsep = pssp->rowsep;
+	}
+
+	return tssp;
+}
+
+/*	TblFindColSpec()  --  find a table colspec by name (colname)
+ *
+ */
+
+
+
+struct tblcolspec *
+TblFindColSpec(char * name,		/* the name we're looking for */
+	       tblsource source)	/* the context in which to find it */
+{
+	struct tblcolspec * tcsp;
+
+
+    /* first, try to find the one in the right "source" */
+
+    	for ( tcsp=tblColSpec;  tcsp;  tcsp=tcsp->next )	{
+    		if ( (tcsp->source == source) && !strcmp(tcsp->name, name) )
+    			return tcsp;
+    	}
+
+    /* else, try to find one from a TGroup.. */
+
+    	for ( tcsp=tblColSpec;  tcsp;  tcsp=tcsp->next )	{
+    		if ( (tcsp->source == TGroup) && !strcmp(tcsp->name, name) )
+    			return tcsp;
+    	}
+
+    /* else not found.. */
+
+	return 0;
+}       
+
+/*	TblFindColNum()  --  find a table colspec by number
+ *
+ */
+
+
+
+struct tblcolspec *
+TblFindColNum(short number,		/* the number we're looking for */
+	      tblsource source)		/* the context in which to find it */
+{
+	struct tblcolspec * tcsp;
+
+
+
+    /* first, try to find the one in the right "source" */
+
+    	for ( tcsp=tblColSpec;  tcsp;  tcsp=tcsp->next )	{
+    		if ( (tcsp->num == number) &&
+    		     ((tcsp->source == source) ||
+    		      ((source == THead) && (tcsp->source == TGroup))) )
+    			return tcsp;
+    	}
+
+    /* else, try to find one from a TGroup.. */
+
+    	for ( tcsp=tblColSpec;  tcsp;  tcsp=tcsp->next )	{
+    		if ( (tcsp->source == TGroup) && (tcsp->num == number) )
+    			return tcsp;
+    	}
+
+    /* else not found.. */
+
+	return 0;
+}
+
+/*	TblFindSpanSpec()  --  find a table spanspec by name (spanname)
+ *
+ */
+
+
+
+struct tblspanspec *
+TblFindSpanSpec(char * name,		/* the name we're looking for */
+	        tblsource source)	/* the context in which to find it */
+{
+	struct tblspanspec * tssp;
+
+
+    /* first, try to find the one in the right "source" */
+
+    	for ( tssp=tblSpanSpec;  tssp;  tssp=tssp->next )	{
+    		if ( !strcmp(tssp->name, name) &&
+    		     ((tssp->source == source) ||
+    		      ((source == THead) && (tssp->source == TGroup))) )
+    			return tssp;
+    	}
+
+    /* else not found.. */
+
+	return 0;
+}
diff --git a/cde/programs/dtdocbook/instant/traninit.c b/cde/programs/dtdocbook/instant/traninit.c
index 70fd8594..0187fc94 100644
--- a/cde/programs/dtdocbook/instant/traninit.c
+++ b/cde/programs/dtdocbook/instant/traninit.c
@@ -54,11 +54,6 @@
  * ________________________________________________________________________
  */
 
-#ifndef lint
-static char *RCSid =
-  "$XConsortium: traninit.c /main/3 1996/06/19 17:13:22 drk $";
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
@@ -127,6 +122,7 @@ ReadTransSpec(
 		while (IsWhite(c)) c = getc(fp);
 		ungetc(c, fp);		/* put back non-whitespace */
 		i = strlen(buf);
+		buf[i++] = ' ';
 		fn = buf + i;		/* point to end of string in buffer */
 		fgets(fn, LINESIZE-i, fp);	/* read and append to buf */
 		lineno++;
diff --git a/cde/programs/dtdocbook/instant/translate.c b/cde/programs/dtdocbook/instant/translate.c
index 70e68bd9..974d060c 100644
--- a/cde/programs/dtdocbook/instant/translate.c
+++ b/cde/programs/dtdocbook/instant/translate.c
@@ -51,11 +51,6 @@
  * ________________________________________________________________________
  */
 
-#ifndef lint
-static char *RCSid =
-  "$XConsortium: translate.c /main/10 1996/10/29 11:47:36 cde-hp $";
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
@@ -664,6 +659,7 @@ DoData(
 		mapped = 1;
 		break;
 	    }
+	    if ( *cp == -1 )	*cp = '^';
 	    if (!mapped) *dp++ = *cp;
 	    prev = *cp;
 	}
diff --git a/cde/programs/dtdocbook/instant/translate.h b/cde/programs/dtdocbook/instant/translate.h
index 49e4019d..fca28c75 100644
--- a/cde/programs/dtdocbook/instant/translate.h
+++ b/cde/programs/dtdocbook/instant/translate.h
@@ -48,13 +48,6 @@
  * ________________________________________________________________________
  */
 
-#ifdef STORAGE
-#ifndef lint
-static char *tr_h_RCSid =
-  "$XConsortium: translate.h /main/3 1996/06/19 17:13:31 drk $";
-#endif
-#endif
-
 #define L_CURLY		'{'
 #define R_CURLY		'}'
 
diff --git a/cde/programs/dtdocbook/instant/tranvar.c b/cde/programs/dtdocbook/instant/tranvar.c
index f2c23f5e..03c527f4 100644
--- a/cde/programs/dtdocbook/instant/tranvar.c
+++ b/cde/programs/dtdocbook/instant/tranvar.c
@@ -48,11 +48,6 @@
  * ________________________________________________________________________
  */
 
-#ifndef lint
-static char *RCSid =
-  "$XConsortium: tranvar.c /main/7 1996/08/08 14:42:09 cde-hp $";
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
@@ -486,13 +481,30 @@ ExpandSpecialVar(
 	else if (*tok[1] == 'E') e->gen_trans[1] = action;
     }
 
-    /* Do an OSF DTD table spec for TeX or troff.  Looks through attributes
+    /* Do an CALS DTD table spec for TeX or troff.  Looks through attributes
      * and determines what to output. "check" means to check consistency,
      * and print error messages.
-     * This is (hopefully) the only hard-coded part of the program.
-     * Format: _osftable [tex|roff|check] [cell|top|bottom|rowend] */
-    else if (StrEq(tok[0], "osftable")) {
-	OSFtable(e, fp, tok, ntok);
+     * This is (hopefully) the only hard-coded part of instant.
+     *
+     * This was originally written for the OSF DTDs and recoded by FLD for
+     * CALS tables (since no one will ever use the OSF tables).  Although
+     * TeX was addressed first, it seems that a fresh approach was required,
+     * and so, tbl is the first to be really *fixed*.  Once tbl is stable,
+     * and there is a need for TeX again, that part will be recoded.
+     *
+     * *Obsolete* form (viz, for TeX):
+     *    Format: _calstable [clear|check|tex]
+     *			  [cellstart|cellend|rowstart|rowend|top|bottom]
+     *
+     * New, good form:
+     *
+     *    Format: _calstable [tbl]
+     *			  [tablestart|tableend|tablegroup|tablefoot|rowstart|
+     *			   rowend|entrystart|entryend]
+     */
+
+    else if (StrEq(tok[0], "calstable")) {
+	CALStable(e, fp, tok, ntok);
     }
 
     /* Do action if element's attr is set, optionally to value.
diff --git a/cde/programs/dtdocbook/instant/util.c b/cde/programs/dtdocbook/instant/util.c
index f4b081e2..1e3c613e 100644
--- a/cde/programs/dtdocbook/instant/util.c
+++ b/cde/programs/dtdocbook/instant/util.c
@@ -65,11 +65,6 @@
  * ________________________________________________________________________
  */
 
-#ifndef lint
-static char *RCSid =
-  "$TOG: util.c /main/13 1997/10/09 16:09:50 bill $";
-#endif
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <ctype.h>
-- 
2.17.1

_______________________________________________
cdesktopenv-devel mailing list
cdesktopenv-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/cdesktopenv-devel

Reply via email to