]> granicus.if.org Git - docbook-dsssl/commitdiff
Fixed a number of significant outstanding table problems; I think HTML and FO now...
authorNorman Walsh <ndw@nwalsh.com>
Sun, 14 Oct 2001 20:27:25 +0000 (20:27 +0000)
committerNorman Walsh <ndw@nwalsh.com>
Sun, 14 Oct 2001 20:27:25 +0000 (20:27 +0000)
xsl/common/table.xsl [new file with mode: 0644]
xsl/fo/table.xsl
xsl/html/table.xsl

diff --git a/xsl/common/table.xsl b/xsl/common/table.xsl
new file mode 100644 (file)
index 0000000..0644dec
--- /dev/null
@@ -0,0 +1,158 @@
+<?xml version="1.0"?>
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:doc="http://nwalsh.com/xsl/documentation/1.0"
+                exclude-result-prefixes="doc"
+                version="1.0">
+
+<xsl:template name="blank.spans">
+  <xsl:param name="cols" select="1"/>
+  <xsl:if test="$cols &gt; 0">
+    <xsl:text>0:</xsl:text>
+    <xsl:call-template name="blank.spans">
+      <xsl:with-param name="cols" select="$cols - 1"/>
+    </xsl:call-template>
+  </xsl:if>
+</xsl:template>
+
+<xsl:template name="calculate.following.spans">
+  <xsl:param name="colspan" select="1"/>
+  <xsl:param name="spans" select="''"/>
+
+  <xsl:choose>
+    <xsl:when test="$colspan &gt; 0">
+      <xsl:call-template name="calculate.following.spans">
+        <xsl:with-param name="colspan" select="$colspan - 1"/>
+        <xsl:with-param name="spans" select="substring-after($spans,':')"/>
+      </xsl:call-template>
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:value-of select="$spans"/>
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+<xsl:template name="finaltd">
+  <xsl:param name="spans"/>
+
+  <xsl:if test="$spans != ''">
+    <xsl:choose>
+      <xsl:when test="starts-with($spans,'0:')">
+        <xsl:call-template name="empty.table.cell"/>
+      </xsl:when>
+      <xsl:otherwise></xsl:otherwise>
+    </xsl:choose>
+
+    <xsl:call-template name="finaltd">
+      <xsl:with-param name="spans" select="substring-after($spans,':')"/>
+    </xsl:call-template>
+  </xsl:if>
+</xsl:template>
+
+<xsl:template name="sfinaltd">
+  <xsl:param name="spans"/>
+
+  <xsl:if test="$spans != ''">
+    <xsl:choose>
+      <xsl:when test="starts-with($spans,'0:')">0:</xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="substring-before($spans,':')-1"/>
+        <xsl:text>:</xsl:text>
+      </xsl:otherwise>
+    </xsl:choose>
+
+    <xsl:call-template name="sfinaltd">
+      <xsl:with-param name="spans" select="substring-after($spans,':')"/>
+    </xsl:call-template>
+  </xsl:if>
+</xsl:template>
+
+<xsl:template name="entry.colnum">
+  <xsl:param name="entry" select="."/>
+
+  <xsl:choose>
+    <xsl:when test="$entry/@colname">
+      <xsl:variable name="colname" select="$entry/@colname"/>
+      <xsl:variable name="colspec"
+                    select="$entry/ancestor::tgroup/colspec[@colname=$colname]"/>
+      <xsl:call-template name="colspec.colnum">
+        <xsl:with-param name="colspec" select="$colspec"/>
+      </xsl:call-template>
+    </xsl:when>
+    <xsl:when test="$entry/@namest">
+      <xsl:variable name="namest" select="$entry/@namest"/>
+      <xsl:variable name="colspec"
+                    select="$entry/ancestor::tgroup/colspec[@colname=$namest]"/>
+      <xsl:call-template name="colspec.colnum">
+        <xsl:with-param name="colspec" select="$colspec"/>
+      </xsl:call-template>
+    </xsl:when>
+    <!-- no idea, return 0 -->
+    <xsl:otherwise>0</xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+<doc:template name="entry.colnum" xmlns="">
+<refpurpose>Determine the column number in which a given entry occurs</refpurpose>
+<refdescription>
+<para>If an <sgmltag>entry</sgmltag> has a
+<sgmltag class="attribute">colname</sgmltag> or
+<sgmltag class="attribute">namest</sgmltag> attribute, this template
+will determine the number of the column in which the entry should occur.
+For other <sgmltag>entry</sgmltag>s, nothing is returned.</para>
+</refdescription>
+<refparameter>
+<variablelist>
+<varlistentry><term>entry</term>
+<listitem>
+<para>The <sgmltag>entry</sgmltag>-element which is to be tested.</para>
+</listitem>
+</varlistentry>
+</variablelist>
+</refparameter>
+
+<refreturn>
+<para>This template returns the column number if it can be determined,
+or 0 (the empty string)</para>
+</refreturn>
+</doc:template>
+
+<xsl:template name="colspec.colnum">
+  <xsl:param name="colspec" select="."/>
+  <xsl:choose>
+    <xsl:when test="$colspec/@colnum">
+      <xsl:value-of select="$colspec/@colnum"/>
+    </xsl:when>
+    <xsl:when test="$colspec/preceding-sibling::colspec">
+      <xsl:variable name="prec.colspec.colnum">
+        <xsl:call-template name="colspec.colnum">
+          <xsl:with-param name="colspec"
+                          select="$colspec/preceding-sibling::colspec[1]"/>
+        </xsl:call-template>
+      </xsl:variable>
+      <xsl:value-of select="$prec.colspec.colnum + 1"/>
+    </xsl:when>
+    <xsl:otherwise>1</xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+<xsl:template name="calculate.colspan">
+  <xsl:param name="entry" select="."/>
+  <xsl:variable name="namest" select="$entry/@namest"/>
+  <xsl:variable name="nameend" select="$entry/@nameend"/>
+
+  <xsl:variable name="scol">
+    <xsl:call-template name="colspec.colnum">
+      <xsl:with-param name="colspec"
+                      select="$entry/ancestor::tgroup/colspec[@colname=$namest]"/>
+    </xsl:call-template>
+  </xsl:variable>
+  <xsl:variable name="ecol">
+    <xsl:call-template name="colspec.colnum">
+      <xsl:with-param name="colspec"
+                      select="$entry/ancestor::tgroup/colspec[@colname=$nameend]"/>
+    </xsl:call-template>
+  </xsl:variable>
+  <xsl:value-of select="$ecol - $scol + 1"/>
+</xsl:template>
+
+</xsl:stylesheet>
index d88a1f1fa9e0a5292259098286826596c824b9ed..393f20acda98185769f66ae2ed9009e4f2aa89ae 100644 (file)
@@ -8,6 +8,8 @@
                 exclude-result-prefixes="doc stbl xtbl lxslt"
                 version='1.0'>
 
+<xsl:include href="../common/table.xsl"/>
+
 <!-- ********************************************************************
      $Id$
      ********************************************************************
@@ -56,6 +58,14 @@ to be incomplete. Don't forget to read the source, too :-)</para>
 
 <!-- ==================================================================== -->
 
+<xsl:template name="empty.table.cell">
+  <fo:table-cell text-align="center" display-align="center">
+    <fo:block/>
+  </fo:table-cell>
+</xsl:template>
+
+<!-- ==================================================================== -->
+
 <xsl:template name="border">
   <xsl:param name="side" select="'left'"/>
   <xsl:param name="padding" select="0"/>
@@ -180,7 +190,15 @@ to be incomplete. Don't forget to read the source, too :-)</para>
         </xsl:call-template>
       </xsl:when>
     </xsl:choose>
-    <xsl:apply-templates/>
+
+    <xsl:apply-templates select="row[1]">
+      <xsl:with-param name="spans">
+        <xsl:call-template name="blank.spans">
+          <xsl:with-param name="cols" select="../@cols"/>
+        </xsl:call-template>
+      </xsl:with-param>
+    </xsl:apply-templates>
+
   </fo:table-header>
 </xsl:template>
 
@@ -204,7 +222,15 @@ to be incomplete. Don't forget to read the source, too :-)</para>
         </xsl:call-template>
       </xsl:when>
     </xsl:choose>
-    <xsl:apply-templates/>
+
+    <xsl:apply-templates select="row[1]">
+      <xsl:with-param name="spans">
+        <xsl:call-template name="blank.spans">
+          <xsl:with-param name="cols" select="../@cols"/>
+        </xsl:call-template>
+      </xsl:with-param>
+    </xsl:apply-templates>
+
   </fo:table-footer>
 </xsl:template>
 
@@ -264,98 +290,277 @@ to be incomplete. Don't forget to read the source, too :-)</para>
         </xsl:call-template>
       </xsl:when>
     </xsl:choose>
-    <xsl:apply-templates/>
+
+    <xsl:apply-templates select="row[1]">
+      <xsl:with-param name="spans">
+        <xsl:call-template name="blank.spans">
+          <xsl:with-param name="cols" select="../@cols"/>
+        </xsl:call-template>
+      </xsl:with-param>
+    </xsl:apply-templates>
+
   </fo:table-body>
 </xsl:template>
 
 <xsl:template match="row">
+  <xsl:param name="spans"/>
+
   <fo:table-row>
+    <xsl:call-template name="anchor"/>
+
     <xsl:if test="@rowsep='1'">
       <xsl:call-template name="border">
         <xsl:with-param name="side" select="'bottom'"/>
       </xsl:call-template>
     </xsl:if>
-    <xsl:apply-templates/>
+
+    <xsl:apply-templates select="entry[1]">
+      <xsl:with-param name="spans" select="$spans"/>
+    </xsl:apply-templates>
   </fo:table-row>
-</xsl:template>
 
-<xsl:template match="thead/row/entry">
-  <xsl:call-template name="process.cell"/>
-</xsl:template>
+  <xsl:if test="following-sibling::row">
+    <xsl:variable name="nextspans">
+      <xsl:apply-templates select="entry[1]" mode="span">
+        <xsl:with-param name="spans" select="$spans"/>
+      </xsl:apply-templates>
+    </xsl:variable>
 
-<xsl:template match="tbody/row/entry">
-  <xsl:call-template name="process.cell"/>
+    <xsl:apply-templates select="following-sibling::row[1]">
+      <xsl:with-param name="spans" select="$nextspans"/>
+    </xsl:apply-templates>
+  </xsl:if>
 </xsl:template>
 
-<xsl:template match="tfoot/row/entry">
-  <xsl:call-template name="process.cell"/>
-</xsl:template>
+<xsl:template match="entry" name="entry">
+  <xsl:param name="col" select="1"/>
+  <xsl:param name="spans"/>
 
-<xsl:template name="process.cell">
   <xsl:variable name="row" select="parent::row"/>
   <xsl:variable name="group" select="$row/parent::*[1]"/>
   <xsl:variable name="frame" select="ancestor::tgroup/parent::*/@frame"/>
 
-  <xsl:variable name="content">
-    <xsl:apply-templates/>
+  <xsl:variable name="empty.cell" select="count(node()) = 0"/>
+
+  <xsl:variable name="entry.colnum">
+    <xsl:call-template name="entry.colnum"/>
   </xsl:variable>
 
-  <fo:table-cell>
+  <xsl:variable name="entry.colspan">
     <xsl:choose>
-      <xsl:when test="$frame='all'">
-        <xsl:call-template name="border">
-          <xsl:with-param name="side" select="'left'"/>
-          <xsl:with-param name="padding" select="1"/>
-        </xsl:call-template>
-        <xsl:call-template name="border">
-          <xsl:with-param name="side" select="'right'"/>
-          <xsl:with-param name="padding" select="1"/>
-        </xsl:call-template>
-        <xsl:call-template name="border">
-          <xsl:with-param name="side" select="'top'"/>
-          <xsl:with-param name="padding" select="1"/>
-        </xsl:call-template>
-        <xsl:call-template name="border">
-          <xsl:with-param name="side" select="'bottom'"/>
-          <xsl:with-param name="padding" select="1"/>
-        </xsl:call-template>
+      <xsl:when test="@namest and @nameend">
+        <xsl:call-template name="calculate.colspan"/>
       </xsl:when>
-      <xsl:otherwise>
-        <xsl:if test="@colsep='1'">
-          <xsl:call-template name="border">
-            <xsl:with-param name="side" select="'right'"/>
-            <xsl:with-param name="padding" select="1"/>
-          </xsl:call-template>
+      <xsl:otherwise>1</xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
+
+  <xsl:variable name="following.spans">
+    <xsl:call-template name="calculate.following.spans">
+      <xsl:with-param name="colspan" select="$entry.colspan"/>
+      <xsl:with-param name="spans" select="$spans"/>
+    </xsl:call-template>
+  </xsl:variable>
+
+  <xsl:choose>
+    <xsl:when test="$spans != '' and not(starts-with($spans,'0:'))">
+      <xsl:call-template name="entry">
+        <xsl:with-param name="col" select="$col+1"/>
+        <xsl:with-param name="spans" select="substring-after($spans,':')"/>
+      </xsl:call-template>
+    </xsl:when>
+
+    <xsl:when test="$entry.colnum &gt; $col">
+      <xsl:call-template name="empty.table.cell"/>
+      <xsl:call-template name="entry">
+        <xsl:with-param name="col" select="$col+1"/>
+        <xsl:with-param name="spans" select="substring-after($spans,':')"/>
+      </xsl:call-template>
+    </xsl:when>
+
+    <xsl:otherwise>
+      <fo:table-cell>
+        <xsl:call-template name="anchor"/>
+
+        <xsl:choose>
+          <xsl:when test="$frame='all'">
+            <xsl:call-template name="border">
+              <xsl:with-param name="side" select="'left'"/>
+              <xsl:with-param name="padding" select="1"/>
+            </xsl:call-template>
+            <xsl:call-template name="border">
+              <xsl:with-param name="side" select="'right'"/>
+              <xsl:with-param name="padding" select="1"/>
+            </xsl:call-template>
+            <xsl:call-template name="border">
+              <xsl:with-param name="side" select="'top'"/>
+              <xsl:with-param name="padding" select="1"/>
+            </xsl:call-template>
+            <xsl:call-template name="border">
+              <xsl:with-param name="side" select="'bottom'"/>
+              <xsl:with-param name="padding" select="1"/>
+            </xsl:call-template>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:if test="@colsep='1'">
+              <xsl:call-template name="border">
+                <xsl:with-param name="side" select="'right'"/>
+                <xsl:with-param name="padding" select="1"/>
+              </xsl:call-template>
+            </xsl:if>
+            <xsl:if test="@rowsep='1'">
+              <xsl:call-template name="border">
+                <xsl:with-param name="side" select="'bottom'"/>
+                <xsl:with-param name="padding" select="1"/>
+              </xsl:call-template>
+            </xsl:if>
+          </xsl:otherwise>
+        </xsl:choose>
+
+        <xsl:if test="@morerows">
+          <xsl:attribute name="number-rows-spanned">
+            <xsl:value-of select="@morerows+1"/>
+          </xsl:attribute>
         </xsl:if>
-        <xsl:if test="@rowsep='1'">
-          <xsl:call-template name="border">
-            <xsl:with-param name="side" select="'bottom'"/>
-            <xsl:with-param name="padding" select="1"/>
-          </xsl:call-template>
+
+        <xsl:if test="$entry.colspan &gt; 1">
+          <xsl:attribute name="number-columns-spanned">
+            <xsl:value-of select="$entry.colspan"/>
+          </xsl:attribute>
         </xsl:if>
-      </xsl:otherwise>
-    </xsl:choose>
 
-    <xsl:if test="@morerows">
-      <xsl:attribute name="number-rows-spanned">
-        <xsl:value-of select="@morerows+1"/>
-      </xsl:attribute>
-    </xsl:if>
-    <xsl:if test="@namest">
-      <xsl:attribute name="column-number">
-        <xsl:call-template name="colspec.colnum">
-          <xsl:with-param name="colname" select="@namest"/>
-        </xsl:call-template>
-      </xsl:attribute>
-      <xsl:attribute name="number-columns-spanned">
+        <xsl:if test="@valign">
+          <xsl:attribute name="display-align">
+            <xsl:choose>
+              <xsl:when test="@valign='top'">before</xsl:when>
+              <xsl:when test="@valign='middle'">center</xsl:when>
+              <xsl:when test="@valign='bottom'">after</xsl:when>
+            </xsl:choose>
+          </xsl:attribute>
+        </xsl:if>
+
+        <xsl:if test="@align">
+          <xsl:attribute name="text-align">
+            <xsl:value-of select="@align"/>
+          </xsl:attribute>
+        </xsl:if>
+
+<!--
+        <xsl:if test="@char">
+          <xsl:attribute name="char">
+            <xsl:value-of select="@char"/>
+          </xsl:attribute>
+        </xsl:if>
+
+        <xsl:if test="@charoff">
+          <xsl:attribute name="charoff">
+            <xsl:value-of select="@charoff"/>
+          </xsl:attribute>
+        </xsl:if>
+
+-->
+
+        <fo:block>
+          <xsl:choose>
+            <xsl:when test="$empty.cell">
+              <xsl:text>&#160;</xsl:text>
+            </xsl:when>
+            <xsl:otherwise>
+              <xsl:apply-templates/>
+            </xsl:otherwise>
+          </xsl:choose>
+        </fo:block>
+      </fo:table-cell>
+
+      <xsl:choose>
+        <xsl:when test="following-sibling::entry">
+          <xsl:apply-templates select="following-sibling::entry[1]">
+            <xsl:with-param name="col" select="$col+$entry.colspan"/>
+            <xsl:with-param name="spans" select="$following.spans"/>
+          </xsl:apply-templates>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:call-template name="finaltd">
+            <xsl:with-param name="spans" select="$following.spans"/>
+          </xsl:call-template>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+<xsl:template match="entry" name="sentry" mode="span">
+  <xsl:param name="col" select="1"/>
+  <xsl:param name="spans"/>
+
+  <xsl:variable name="entry.colnum">
+    <xsl:call-template name="entry.colnum"/>
+  </xsl:variable>
+
+  <xsl:variable name="entry.colspan">
+    <xsl:choose>
+      <xsl:when test="@namest and @nameend">
         <xsl:call-template name="calculate.colspan"/>
-      </xsl:attribute>
-    </xsl:if>
+      </xsl:when>
+      <xsl:otherwise>1</xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
 
-    <fo:block>
-      <xsl:copy-of select="$content"/>
-    </fo:block>
-  </fo:table-cell>
+  <xsl:variable name="following.spans">
+    <xsl:call-template name="calculate.following.spans">
+      <xsl:with-param name="colspan" select="$entry.colspan"/>
+      <xsl:with-param name="spans" select="$spans"/>
+    </xsl:call-template>
+  </xsl:variable>
+
+  <xsl:choose>
+    <xsl:when test="$spans != '' and not(starts-with($spans,'0:'))">
+      <xsl:value-of select="substring-before($spans,':')-1"/>
+      <xsl:text>:</xsl:text>
+      <xsl:call-template name="sentry">
+        <xsl:with-param name="col" select="$col+1"/>
+        <xsl:with-param name="spans" select="substring-after($spans,':')"/>
+      </xsl:call-template>
+    </xsl:when>
+
+    <xsl:when test="$entry.colnum &gt; $col">
+      <xsl:text>0:</xsl:text>
+      <xsl:call-template name="sentry">
+        <xsl:with-param name="col" select="$col+$entry.colspan"/>
+        <xsl:with-param name="spans" select="$following.spans"/>
+      </xsl:call-template>
+    </xsl:when>
+
+    <xsl:otherwise>
+      <xsl:call-template name="copy-string">
+        <xsl:with-param name="count" select="$entry.colspan"/>
+        <xsl:with-param name="string">
+          <xsl:choose>
+            <xsl:when test="@morerows">
+              <xsl:value-of select="@morerows"/>
+            </xsl:when>
+            <xsl:otherwise>0</xsl:otherwise>
+          </xsl:choose>
+          <xsl:text>:</xsl:text>
+        </xsl:with-param>
+      </xsl:call-template>
+
+      <xsl:choose>
+        <xsl:when test="following-sibling::entry">
+          <xsl:apply-templates select="following-sibling::entry[1]"
+                               mode="span">
+            <xsl:with-param name="col" select="$col+$entry.colspan"/>
+            <xsl:with-param name="spans" select="$following.spans"/>
+          </xsl:apply-templates>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:call-template name="sfinaltd">
+            <xsl:with-param name="spans" select="$following.spans"/>
+          </xsl:call-template>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:otherwise>
+  </xsl:choose>
 </xsl:template>
 
 <xsl:template name="generate.colgroup.raw">
@@ -671,69 +876,6 @@ proportional-column-width() function.</para>
   </xsl:choose>
 </xsl:template>
 
-<xsl:template name="colspec.colnum">
-  <!-- when this macro is called, the current context must be an entry -->
-  <xsl:param name="colname"></xsl:param>
-  <!-- .. = row, ../.. = thead|tbody, ../../.. = tgroup -->
-  <xsl:param name="colspecs" select="../../../../tgroup/colspec"/>
-  <xsl:param name="count">1</xsl:param>
-  <xsl:param name="colnum">1</xsl:param>
-  <xsl:choose>
-    <xsl:when test="$count>count($colspecs)"></xsl:when>
-    <xsl:otherwise>
-      <xsl:variable name="colspec" select="$colspecs[$count=position()]"/>
-<!--
-      <xsl:value-of select="$count"/>:
-      <xsl:value-of select="$colspec/@colname"/>=
-      <xsl:value-of select="$colnum"/>
--->
-      <xsl:choose>
-        <xsl:when test="$colspec/@colname=$colname">
-          <xsl:choose>
-            <xsl:when test="$colspec/@colnum">
-              <xsl:value-of select="$colspec/@colnum"/>
-            </xsl:when>
-            <xsl:otherwise>
-              <xsl:value-of select="$colnum"/>
-            </xsl:otherwise>
-          </xsl:choose>
-        </xsl:when>
-        <xsl:otherwise>
-          <xsl:call-template name="colspec.colnum">
-            <xsl:with-param name="colname" select="$colname"/>
-            <xsl:with-param name="colspecs" select="$colspecs"/>
-            <xsl:with-param name="count" select="$count+1"/>
-            <xsl:with-param name="colnum">
-              <xsl:choose>
-                <xsl:when test="$colspec/@colnum">
-                  <xsl:value-of select="$colspec/@colnum + 1"/>
-                </xsl:when>
-                <xsl:otherwise>
-                  <xsl:value-of select="$colnum + 1"/>
-                </xsl:otherwise>
-              </xsl:choose>
-            </xsl:with-param>
-           </xsl:call-template>
-        </xsl:otherwise>
-      </xsl:choose>
-    </xsl:otherwise>
-  </xsl:choose>
-</xsl:template>
-
-<xsl:template name="calculate.colspan">
-  <xsl:variable name="scol">
-    <xsl:call-template name="colspec.colnum">
-      <xsl:with-param name="colname" select="@namest"/>
-    </xsl:call-template>
-  </xsl:variable>
-  <xsl:variable name="ecol">
-    <xsl:call-template name="colspec.colnum">
-      <xsl:with-param name="colname" select="@nameend"/>
-    </xsl:call-template>
-  </xsl:variable>
-  <xsl:value-of select="$ecol - $scol + 1"/>
-</xsl:template>
-
 <!-- ==================================================================== -->
 
 </xsl:stylesheet>
index 63b1ac34ecebeeaacd14f319dbbd9338f941cbba..a3d9f9be87f32d5a344b9cbc59bc37ed68cf71ab 100644 (file)
@@ -7,6 +7,8 @@
                 exclude-result-prefixes="doc stbl xtbl lxslt"
                 version='1.0'>
 
+<xsl:include href="../common/table.xsl"/>
+
 <!-- ********************************************************************
      $Id$
      ********************************************************************
 <lxslt:component prefix="xtbl"
                  functions="adjustColumnWidths"/>
 
+<xsl:template name="empty.table.cell">
+  <td class="auto-generated">&#160;</td>
+</xsl:template>
+
 <xsl:template match="tgroup">
   <table>
     <xsl:choose>
       <xsl:attribute name="width">100%</xsl:attribute>
     </xsl:if>
 
-<!-- this is wrong, align on tgroup gives the default alignment for table
-     cells, not the alignment for the table itself...
-    <xsl:if test="@align">
-      <xsl:attribute name="align">
-        <xsl:value-of select="@align"/>
-      </xsl:attribute>
-    </xsl:if>
--->
-
     <xsl:choose>
       <xsl:when test="../@frame='none'">
         <xsl:attribute name="border">0</xsl:attribute>
       </xsl:attribute>
     </xsl:if>
 
-    <xsl:apply-templates/>
+    <xsl:apply-templates select="row[1]">
+      <xsl:with-param name="spans">
+        <xsl:call-template name="blank.spans">
+          <xsl:with-param name="cols" select="../@cols"/>
+        </xsl:call-template>
+      </xsl:with-param>
+    </xsl:apply-templates>
+
   </xsl:element>
 </xsl:template>
 
       </xsl:attribute>
     </xsl:if>
 
-    <xsl:apply-templates/>
+    <xsl:apply-templates select="row[1]">
+      <xsl:with-param name="spans">
+        <xsl:call-template name="blank.spans">
+          <xsl:with-param name="cols" select="../@cols"/>
+        </xsl:call-template>
+      </xsl:with-param>
+    </xsl:apply-templates>
+
   </tbody>
 </xsl:template>
 
 <xsl:template match="row">
+  <xsl:param name="spans"/>
+
   <tr>
     <xsl:if test="@align">
       <xsl:attribute name="align">
       </xsl:attribute>
     </xsl:if>
 
-    <xsl:apply-templates/>
+    <xsl:apply-templates select="entry[1]">
+      <xsl:with-param name="spans" select="$spans"/>
+    </xsl:apply-templates>
   </tr>
-</xsl:template>
 
-<xsl:template match="thead/row/entry">
-  <xsl:call-template name="process.cell">
-    <xsl:with-param name="cellgi">th</xsl:with-param>
-  </xsl:call-template>
-</xsl:template>
+  <xsl:if test="following-sibling::row">
+    <xsl:variable name="nextspans">
+      <xsl:apply-templates select="entry[1]" mode="span">
+        <xsl:with-param name="spans" select="$spans"/>
+      </xsl:apply-templates>
+    </xsl:variable>
 
-<xsl:template match="tbody/row/entry">
-  <xsl:call-template name="process.cell">
-    <xsl:with-param name="cellgi">td</xsl:with-param>
-  </xsl:call-template>
+    <xsl:apply-templates select="following-sibling::row[1]">
+      <xsl:with-param name="spans" select="$nextspans"/>
+    </xsl:apply-templates>
+  </xsl:if>
 </xsl:template>
 
-<xsl:template match="tfoot/row/entry">
-  <xsl:call-template name="process.cell">
-    <xsl:with-param name="cellgi">th</xsl:with-param>
-  </xsl:call-template>
-</xsl:template>
+<xsl:template match="entry" name="entry">
+  <xsl:param name="col" select="1"/>
+  <xsl:param name="spans"/>
+
+  <xsl:variable name="cellgi">
+    <xsl:choose>
+      <xsl:when test="ancestor::thead">th</xsl:when>
+      <xsl:when test="ancestor::tfoot">th</xsl:when>
+      <xsl:otherwise>td</xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
 
-<xsl:template name="process.cell">
-  <xsl:param name="cellgi">td</xsl:param>
   <xsl:variable name="empty.cell" select="count(node()) = 0"/>
 
   <xsl:variable name="entry.colnum">
     <xsl:call-template name="entry.colnum"/>
   </xsl:variable>
 
-  <xsl:if test="$entry.colnum != ''">
-    <xsl:variable name="prev.entry" select="preceding-sibling::*[1]"/>
-    <xsl:variable name="prev.ending.colnum">
-      <xsl:choose>
-        <xsl:when test="$prev.entry">
-          <xsl:call-template name="entry.ending.colnum">
-            <xsl:with-param name="entry" select="$prev.entry"/>
-          </xsl:call-template>
-        </xsl:when>
-        <xsl:otherwise>0</xsl:otherwise>
-      </xsl:choose>
-    </xsl:variable>
-
-    <!-- 1.31: removed add-empty-entries; there's no practical way for
-         XSLT to keep track of "overhang" from morerows in previous rows.
-         At least none that I can think of. -->
-  </xsl:if>
-
-  <xsl:element name="{$cellgi}">
-    <xsl:if test="@morerows">
-      <xsl:attribute name="rowspan">
-        <xsl:value-of select="@morerows+1"/>
-      </xsl:attribute>
-    </xsl:if>
-    <xsl:if test="@namest">
-      <xsl:attribute name="colspan">
-        <xsl:call-template name="calculate.colspan"/>
-      </xsl:attribute>
-    </xsl:if>
-    <xsl:if test="@align">
-      <xsl:attribute name="align">
-        <xsl:value-of select="@align"/>
-      </xsl:attribute>
-    </xsl:if>
-    <xsl:if test="@char">
-      <xsl:attribute name="char">
-        <xsl:value-of select="@char"/>
-      </xsl:attribute>
-    </xsl:if>
-    <xsl:if test="@charoff">
-      <xsl:attribute name="charoff">
-        <xsl:value-of select="@charoff"/>
-      </xsl:attribute>
-    </xsl:if>
-    <xsl:if test="@valign">
-      <xsl:attribute name="valign">
-        <xsl:value-of select="@valign"/>
-      </xsl:attribute>
-    </xsl:if>
-
-    <xsl:if test="not(preceding-sibling::*)
-                  and ancestor::row/@id">
-      <xsl:call-template name="anchor">
-        <xsl:with-param name="node" select="ancestor::row[1]"/>
-      </xsl:call-template>
-    </xsl:if>
-
-    <xsl:call-template name="anchor"/>
-
+  <xsl:variable name="entry.colspan">
     <xsl:choose>
-      <xsl:when test="$empty.cell">
-        <xsl:text>&#160;</xsl:text>
+      <xsl:when test="@namest and @nameend">
+        <xsl:call-template name="calculate.colspan"/>
       </xsl:when>
-      <xsl:otherwise>
-        <xsl:apply-templates/>
-      </xsl:otherwise>
+      <xsl:otherwise>1</xsl:otherwise>
     </xsl:choose>
-  </xsl:element>
-</xsl:template>
+  </xsl:variable>
 
-<xsl:template name="entry.colnum">
-  <xsl:param name="entry" select="."/>
+  <xsl:variable name="following.spans">
+    <xsl:call-template name="calculate.following.spans">
+      <xsl:with-param name="colspan" select="$entry.colspan"/>
+      <xsl:with-param name="spans" select="$spans"/>
+    </xsl:call-template>
+  </xsl:variable>
 
   <xsl:choose>
-    <xsl:when test="$entry/@colname">
-      <xsl:variable name="colname" select="$entry/@colname"/>
-      <xsl:variable name="colspec"
-                    select="$entry/ancestor::tgroup/colspec[@colname=$colname]"/>
-      <xsl:call-template name="colspec.colnum">
-        <xsl:with-param name="colspec" select="$colspec"/>
+    <xsl:when test="$spans != '' and not(starts-with($spans,'0:'))">
+      <xsl:call-template name="entry">
+        <xsl:with-param name="col" select="$col+1"/>
+        <xsl:with-param name="spans" select="substring-after($spans,':')"/>
       </xsl:call-template>
     </xsl:when>
-    <xsl:when test="$entry/@namest">
-      <xsl:variable name="namest" select="$entry/@namest"/>
-      <xsl:variable name="colspec"
-                    select="$entry/ancestor::tgroup/colspec[@colname=$namest]"/>
-      <xsl:call-template name="colspec.colnum">
-        <xsl:with-param name="colspec" select="$colspec"/>
+
+    <xsl:when test="$entry.colnum &gt; $col">
+      <xsl:call-template name="empty.table.cell"/>
+      <xsl:call-template name="entry">
+        <xsl:with-param name="col" select="$col+1"/>
+        <xsl:with-param name="spans" select="substring-after($spans,':')"/>
       </xsl:call-template>
     </xsl:when>
-    <xsl:when test="count($entry/preceding-sibling::*) = 0">1</xsl:when>
+
     <xsl:otherwise>
-      <xsl:variable name="pcol">
-        <xsl:call-template name="entry.ending.colnum">
-          <xsl:with-param name="entry"
-                          select="$entry/preceding-sibling::*[1]"/>
-        </xsl:call-template>
-      </xsl:variable>
-      <xsl:value-of select="$pcol + 1"/>
+      <xsl:element name="{$cellgi}">
+        <xsl:if test="@morerows &gt; 0">
+          <xsl:attribute name="rowspan">
+            <xsl:value-of select="1+@morerows"/>
+          </xsl:attribute>
+        </xsl:if>
+
+        <xsl:if test="$entry.colspan &gt; 1">
+          <xsl:attribute name="colspan">
+            <xsl:value-of select="$entry.colspan"/>
+          </xsl:attribute>
+        </xsl:if>
+
+        <xsl:if test="@align">
+          <xsl:attribute name="align">
+            <xsl:value-of select="@align"/>
+          </xsl:attribute>
+        </xsl:if>
+
+        <xsl:if test="@char">
+          <xsl:attribute name="char">
+            <xsl:value-of select="@char"/>
+          </xsl:attribute>
+        </xsl:if>
+
+        <xsl:if test="@charoff">
+          <xsl:attribute name="charoff">
+            <xsl:value-of select="@charoff"/>
+          </xsl:attribute>
+        </xsl:if>
+
+        <xsl:if test="@valign">
+          <xsl:attribute name="valign">
+            <xsl:value-of select="@valign"/>
+          </xsl:attribute>
+        </xsl:if>
+
+        <xsl:if test="not(preceding-sibling::*)
+                      and ancestor::row/@id">
+          <xsl:call-template name="anchor">
+            <xsl:with-param name="node" select="ancestor::row[1]"/>
+          </xsl:call-template>
+        </xsl:if>
+
+        <xsl:call-template name="anchor"/>
+
+        <xsl:choose>
+          <xsl:when test="$empty.cell">
+            <xsl:text>&#160;</xsl:text>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:apply-templates/>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:element>
+
+      <xsl:choose>
+        <xsl:when test="following-sibling::entry">
+          <xsl:apply-templates select="following-sibling::entry[1]">
+            <xsl:with-param name="col" select="$col+$entry.colspan"/>
+            <xsl:with-param name="spans" select="$following.spans"/>
+          </xsl:apply-templates>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:call-template name="finaltd">
+            <xsl:with-param name="spans" select="$following.spans"/>
+          </xsl:call-template>
+        </xsl:otherwise>
+      </xsl:choose>
     </xsl:otherwise>
   </xsl:choose>
 </xsl:template>
 
-<doc:template name="entry.colnum" xmlns="">
-<refpurpose>Determine the column number in which a given entry occurs</refpurpose>
-<refdescription>
-<para>If an <sgmltag>entry</sgmltag> has a
-<sgmltag class="attribute">colname</sgmltag> or
-<sgmltag class="attribute">namest</sgmltag> attribute, this template
-will determine the number of the column in which the entry should occur.
-For other <sgmltag>entry</sgmltag>s, nothing is returned.</para>
-</refdescription>
-<refparameter>
-<variablelist>
-<varlistentry><term>entry</term>
-<listitem>
-<para>The <sgmltag>entry</sgmltag>-element which is to be tested.</para>
-</listitem>
-</varlistentry>
-</variablelist>
-</refparameter>
-
-<refreturn>
-<para>This template returns the column number if it can be determined,
-or nothing (the empty string)</para>
-</refreturn>
-</doc:template>
-
-<xsl:template name="entry.ending.colnum">
-  <xsl:param name="entry" select="."/>
+<xsl:template match="entry" name="sentry" mode="span">
+  <xsl:param name="col" select="1"/>
+  <xsl:param name="spans"/>
+
+  <xsl:variable name="entry.colnum">
+    <xsl:call-template name="entry.colnum"/>
+  </xsl:variable>
+
+  <xsl:variable name="entry.colspan">
+    <xsl:choose>
+      <xsl:when test="@namest and @nameend">
+        <xsl:call-template name="calculate.colspan"/>
+      </xsl:when>
+      <xsl:otherwise>1</xsl:otherwise>
+    </xsl:choose>
+  </xsl:variable>
+
+  <xsl:variable name="following.spans">
+    <xsl:call-template name="calculate.following.spans">
+      <xsl:with-param name="colspan" select="$entry.colspan"/>
+      <xsl:with-param name="spans" select="$spans"/>
+    </xsl:call-template>
+  </xsl:variable>
 
   <xsl:choose>
-    <xsl:when test="$entry/@colname">
-      <xsl:variable name="colname" select="$entry/@colname"/>
-      <xsl:variable name="colspec"
-                    select="$entry/ancestor::tgroup/colspec[@colname=$colname]"/>
-      <xsl:call-template name="colspec.colnum">
-        <xsl:with-param name="colspec" select="$colspec"/>
+    <xsl:when test="$spans != '' and not(starts-with($spans,'0:'))">
+      <xsl:value-of select="substring-before($spans,':')-1"/>
+      <xsl:text>:</xsl:text>
+      <xsl:call-template name="sentry">
+        <xsl:with-param name="col" select="$col+1"/>
+        <xsl:with-param name="spans" select="substring-after($spans,':')"/>
       </xsl:call-template>
     </xsl:when>
-    <xsl:when test="$entry/@nameend">
-      <xsl:variable name="nameend" select="$entry/@nameend"/>
-      <xsl:variable name="colspec"
-                    select="$entry/ancestor::tgroup/colspec[@colname=$nameend]"/>
-      <xsl:call-template name="colspec.colnum">
-        <xsl:with-param name="colspec" select="$colspec"/>
+
+    <xsl:when test="$entry.colnum &gt; $col">
+      <xsl:text>0:</xsl:text>
+      <xsl:call-template name="sentry">
+        <xsl:with-param name="col" select="$col+$entry.colspan"/>
+        <xsl:with-param name="spans" select="$following.spans"/>
       </xsl:call-template>
     </xsl:when>
-    <xsl:when test="count($entry/preceding-sibling::*) = 0">1</xsl:when>
-    <xsl:otherwise>
-      <xsl:variable name="pcol">
-        <xsl:call-template name="entry.ending.colnum">
-          <xsl:with-param name="entry"
-                          select="$entry/preceding-sibling::*[1]"/>
-        </xsl:call-template>
-      </xsl:variable>
-      <xsl:value-of select="$pcol + 1"/>
-    </xsl:otherwise>
-  </xsl:choose>
-</xsl:template>
 
+    <xsl:otherwise>
+      <xsl:call-template name="copy-string">
+        <xsl:with-param name="count" select="$entry.colspan"/>
+        <xsl:with-param name="string">
+          <xsl:choose>
+            <xsl:when test="@morerows">
+              <xsl:value-of select="@morerows"/>
+            </xsl:when>
+            <xsl:otherwise>0</xsl:otherwise>
+          </xsl:choose>
+          <xsl:text>:</xsl:text>
+        </xsl:with-param>
+      </xsl:call-template>
 
-<xsl:template name="colspec.colnum">
-  <xsl:param name="colspec" select="."/>
-  <xsl:choose>
-    <xsl:when test="$colspec/@colnum">
-      <xsl:value-of select="$colspec/@colnum"/>
-    </xsl:when>
-    <xsl:when test="$colspec/preceding-sibling::colspec">
-      <xsl:variable name="prec.colspec.colnum">
-        <xsl:call-template name="colspec.colnum">
-          <xsl:with-param name="colspec"
-                          select="$colspec/preceding-sibling::colspec[1]"/>
-        </xsl:call-template>
-      </xsl:variable>
-      <xsl:value-of select="$prec.colspec.colnum + 1"/>
-    </xsl:when>
-    <xsl:otherwise>1</xsl:otherwise>
+      <xsl:choose>
+        <xsl:when test="following-sibling::entry">
+          <xsl:apply-templates select="following-sibling::entry[1]"
+                               mode="span">
+            <xsl:with-param name="col" select="$col+$entry.colspan"/>
+            <xsl:with-param name="spans" select="$following.spans"/>
+          </xsl:apply-templates>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:call-template name="sfinaltd">
+            <xsl:with-param name="spans" select="$following.spans"/>
+          </xsl:call-template>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:otherwise>
   </xsl:choose>
 </xsl:template>
 
@@ -604,25 +622,5 @@ or nothing (the empty string)</para>
   </xsl:choose>
 </xsl:template>
 
-<xsl:template name="calculate.colspan">
-  <xsl:param name="entry" select="."/>
-  <xsl:variable name="namest" select="$entry/@namest"/>
-  <xsl:variable name="nameend" select="$entry/@nameend"/>
-
-  <xsl:variable name="scol">
-    <xsl:call-template name="colspec.colnum">
-      <xsl:with-param name="colspec"
-                      select="$entry/ancestor::tgroup/colspec[@colname=$namest]"/>
-    </xsl:call-template>
-  </xsl:variable>
-  <xsl:variable name="ecol">
-    <xsl:call-template name="colspec.colnum">
-      <xsl:with-param name="colspec"
-                      select="$entry/ancestor::tgroup/colspec[@colname=$nameend]"/>
-    </xsl:call-template>
-  </xsl:variable>
-  <xsl:value-of select="$ecol - $scol + 1"/>
-</xsl:template>
-
 </xsl:stylesheet>