Bump to docbook-xsl-stylesheets 1.79.2
[platform/upstream/docbook-xsl-stylesheets.git] / fo / table.xsl
1 <?xml version='1.0'?>
2 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3                 xmlns:d="http://docbook.org/ns/docbook"
4                 xmlns:doc="http://nwalsh.com/xsl/documentation/1.0"
5                 xmlns:fo="http://www.w3.org/1999/XSL/Format"
6                 xmlns:rx="http://www.renderx.com/XSL/Extensions"
7                 xmlns:stbl="http://nwalsh.com/xslt/ext/com.nwalsh.saxon.Table"
8                 xmlns:xtbl="com.nwalsh.xalan.Table"
9                 xmlns:lxslt="http://xml.apache.org/xslt"
10                 xmlns:ptbl="http://nwalsh.com/xslt/ext/xsltproc/python/Table"
11                 exclude-result-prefixes="doc stbl xtbl lxslt ptbl d"
12                 version='1.0'>
13
14 <xsl:include href="../common/table.xsl"/>
15
16 <!-- ********************************************************************
17
18      This file is part of the XSL DocBook Stylesheet distribution.
19      See ../README or http://cdn.docbook.org/release/xsl/current/ for
20      copyright and other information.
21
22      ******************************************************************** -->
23
24 <doc:reference xmlns="" xml:id="table-templates">
25   <?dbhtml dir="fo"?>
26   <info>
27     <title>Formatting Object Table Reference</title>
28     <releaseinfo role="meta">
29     </releaseinfo>
30   </info>
31   <partintro xml:id="partintro">
32     <title>Introduction</title>
33     <para>This is technical reference documentation for the FO
34       table-processing templates in the DocBook XSL Stylesheets.</para>
35     <para>This is not intended to be user documentation.  It is
36       provided for developers writing customization layers for the
37       stylesheets.</para>
38   </partintro>
39 </doc:reference>
40
41 <!-- ==================================================================== -->
42
43 <lxslt:component prefix="xtbl"
44                  functions="adjustColumnWidths"/>
45
46 <!-- ==================================================================== -->
47
48 <xsl:template name="make.table.content">
49   <xsl:choose>
50     <xsl:when test="d:tgroup|d:mediaobject|d:graphic">
51       <xsl:call-template name="calsTable"/>
52     </xsl:when>
53     <xsl:otherwise>
54       <xsl:apply-templates select="." mode="htmlTable"/>
55     </xsl:otherwise>
56   </xsl:choose>
57 </xsl:template>
58
59 <!-- ==================================================================== -->
60
61 <xsl:template name="calsTable">
62
63   <xsl:variable name="keep.together">
64     <xsl:call-template name="pi.dbfo_keep-together"/>
65   </xsl:variable>
66
67   <xsl:for-each select="d:tgroup">
68
69     <fo:table xsl:use-attribute-sets="table.table.properties">
70       <xsl:if test="$keep.together != ''">
71         <xsl:attribute name="keep-together.within-column">
72           <xsl:value-of select="$keep.together"/>
73         </xsl:attribute>
74       </xsl:if>
75       <xsl:call-template name="table.frame"/>
76       <xsl:if test="following-sibling::d:tgroup">
77         <xsl:attribute name="border-bottom-width">0pt</xsl:attribute>
78         <xsl:attribute name="border-bottom-style">none</xsl:attribute>
79         <xsl:attribute name="padding-bottom">0pt</xsl:attribute>
80         <xsl:attribute name="margin-bottom">0pt</xsl:attribute>
81         <xsl:attribute name="space-after">0pt</xsl:attribute>
82         <xsl:attribute name="space-after.minimum">0pt</xsl:attribute>
83         <xsl:attribute name="space-after.optimum">0pt</xsl:attribute>
84         <xsl:attribute name="space-after.maximum">0pt</xsl:attribute>
85       </xsl:if>
86       <xsl:if test="preceding-sibling::d:tgroup">
87         <xsl:attribute name="border-top-width">0pt</xsl:attribute>
88         <xsl:attribute name="border-top-style">none</xsl:attribute>
89         <xsl:attribute name="padding-top">0pt</xsl:attribute>
90         <xsl:attribute name="margin-top">0pt</xsl:attribute>
91         <xsl:attribute name="space-before">0pt</xsl:attribute>
92         <xsl:attribute name="space-before.minimum">0pt</xsl:attribute>
93         <xsl:attribute name="space-before.optimum">0pt</xsl:attribute>
94         <xsl:attribute name="space-before.maximum">0pt</xsl:attribute>
95       </xsl:if>
96       <xsl:apply-templates select="."/>
97     </fo:table>
98
99     <xsl:for-each select="d:mediaobject|d:graphic">
100       <xsl:apply-templates select="."/>
101     </xsl:for-each>
102
103   </xsl:for-each>
104
105   <xsl:apply-templates select="d:caption"/>
106
107 </xsl:template>
108
109 <!-- ==================================================================== -->
110
111 <!-- Placeholder template enables wrapping a fo:table in
112      another table for purposes of layout or applying
113      extensions such as XEP table-omit-initial-header to
114      create "continued" titles on page breaks. -->
115 <xsl:template name="table.layout">
116   <xsl:param name="table.content" select="NOTANODE"/>
117
118   <xsl:copy-of select="$table.content"/>
119 </xsl:template>
120
121 <xsl:template name="table.block">
122   <xsl:param name="table.layout" select="NOTANODE"/>
123
124   <xsl:variable name="id">
125     <xsl:call-template name="object.id"/>
126   </xsl:variable>
127
128   <xsl:variable name="param.placement"
129                 select="substring-after(normalize-space(
130                    $formal.title.placement), concat(local-name(.), ' '))"/>
131
132   <xsl:variable name="placement">
133     <xsl:choose>
134       <xsl:when test="contains($param.placement, ' ')">
135         <xsl:value-of select="substring-before($param.placement, ' ')"/>
136       </xsl:when>
137       <xsl:when test="$param.placement = ''">before</xsl:when>
138       <xsl:otherwise>
139         <xsl:value-of select="$param.placement"/>
140       </xsl:otherwise>
141     </xsl:choose>
142   </xsl:variable>
143
144   <xsl:variable name="keep.together">
145     <xsl:call-template name="pi.dbfo_keep-together"/>
146   </xsl:variable>
147
148   <xsl:choose>
149     <xsl:when test="self::d:table">
150       <fo:block id="{$id}"
151                 xsl:use-attribute-sets="table.properties">
152         <xsl:if test="$keep.together != ''">
153           <xsl:attribute name="keep-together.within-column">
154             <xsl:value-of select="$keep.together"/>
155           </xsl:attribute>
156         </xsl:if>
157         <xsl:if test="$placement = 'before'">
158           <xsl:call-template name="formal.object.heading">
159             <xsl:with-param name="placement" select="$placement"/>
160           </xsl:call-template>
161         </xsl:if>
162         <xsl:copy-of select="$table.layout"/>
163         <xsl:call-template name="table.footnote.block"/>
164         <xsl:if test="$placement != 'before'">
165           <xsl:call-template name="formal.object.heading">
166             <xsl:with-param name="placement" select="$placement"/>
167           </xsl:call-template>
168         </xsl:if>
169       </fo:block>
170     </xsl:when>
171     <xsl:otherwise>
172       <fo:block id="{$id}"
173                 xsl:use-attribute-sets="informaltable.properties">
174         <xsl:if test="$keep.together != ''">
175           <xsl:attribute name="keep-together.within-column">
176             <xsl:value-of select="$keep.together"/>
177           </xsl:attribute>
178         </xsl:if>
179         <xsl:copy-of select="$table.layout"/>
180         <xsl:call-template name="table.footnote.block"/>
181       </fo:block>
182     </xsl:otherwise>
183   </xsl:choose>
184
185
186 </xsl:template>
187
188 <!-- Output a table's footnotes in a block -->
189 <xsl:template name="table.footnote.block">
190   <xsl:if test=".//d:footnote">
191     <fo:block keep-with-previous.within-column="always">
192       <xsl:apply-templates select=".//d:footnote" mode="table.footnote.mode"/>
193     </fo:block>
194   </xsl:if>
195 </xsl:template>
196
197 <!-- ==================================================================== -->
198
199 <xsl:template name="table.container">
200   <xsl:param name="table.block"/>
201   <xsl:choose>
202     <xsl:when test="@orient='land' and 
203                     $fop.extensions = 0" >
204       <fo:block-container reference-orientation="90"
205             padding="6pt"
206             xsl:use-attribute-sets="list.block.spacing">
207         <xsl:attribute name="width">
208           <xsl:call-template name="table.width"/>
209         </xsl:attribute>
210         <fo:block start-indent="0pt" end-indent="0pt">
211           <xsl:copy-of select="$table.block"/>
212         </fo:block>
213       </fo:block-container>
214     </xsl:when>
215     <xsl:when test="@pgwide = 1">
216       <fo:block xsl:use-attribute-sets="pgwide.properties">
217         <xsl:copy-of select="$table.block"/>
218       </fo:block>
219     </xsl:when>
220     <xsl:otherwise>
221       <xsl:copy-of select="$table.block"/>
222     </xsl:otherwise>
223   </xsl:choose>
224 </xsl:template>
225
226 <!-- ==================================================================== -->
227
228 <xsl:template name="empty.table.cell">
229   <xsl:param name="colnum" select="0"/>
230
231   <xsl:variable name="rowsep">
232     <xsl:choose>
233       <!-- If this is the last row, rowsep never applies (except when 
234            the ancestor tgroup has a following sibling tgroup) -->
235       <xsl:when test="not(ancestor-or-self::d:row[1]/following-sibling::d:row
236                           or ancestor-or-self::d:thead/following-sibling::d:tbody
237                           or ancestor-or-self::d:tbody/preceding-sibling::d:tfoot)
238                           and not(ancestor::d:tgroup/following-sibling::d:tgroup)">
239         <xsl:value-of select="0"/>
240       </xsl:when>
241       <xsl:otherwise>
242         <xsl:call-template name="inherited.table.attribute">
243           <xsl:with-param name="entry" select="NOT-AN-ELEMENT-NAME"/>
244           <xsl:with-param name="row" select="ancestor-or-self::d:row[1]"/>
245           <xsl:with-param name="colnum" select="$colnum"/>
246           <xsl:with-param name="attribute" select="'rowsep'"/>
247         </xsl:call-template>
248       </xsl:otherwise>
249     </xsl:choose>
250   </xsl:variable>
251
252   <xsl:variable name="colsep">
253     <xsl:choose>
254       <!-- If this is the last column, colsep never applies. -->
255       <xsl:when test="number($colnum) &gt;= ancestor::d:tgroup/@cols">0</xsl:when>
256       <xsl:otherwise>
257         <xsl:call-template name="inherited.table.attribute">
258           <xsl:with-param name="entry" select="NOT-AN-ELEMENT-NAME"/>
259           <xsl:with-param name="row" select="ancestor-or-self::d:row[1]"/>
260           <xsl:with-param name="colnum" select="$colnum"/>
261           <xsl:with-param name="attribute" select="'colsep'"/>
262         </xsl:call-template>
263       </xsl:otherwise>
264     </xsl:choose>
265   </xsl:variable>
266
267   <fo:table-cell text-align="center"
268                  display-align="center"
269                  xsl:use-attribute-sets="table.cell.padding">
270     <xsl:if test="$xep.extensions != 0">
271       <!-- Suggested by RenderX to workaround a bug in their implementation -->
272       <xsl:attribute name="keep-together.within-column">always</xsl:attribute>
273     </xsl:if>
274     <xsl:if test="$rowsep &gt; 0">
275       <xsl:call-template name="border">
276         <xsl:with-param name="side" select="'bottom'"/>
277       </xsl:call-template>
278     </xsl:if>
279
280     <xsl:if test="$colsep &gt; 0 and number($colnum) &lt; ancestor::d:tgroup/@cols">
281       <xsl:call-template name="border">
282         <xsl:with-param name="side" select="'end'"/>
283       </xsl:call-template>
284     </xsl:if>
285
286     <!-- fo:table-cell should not be empty -->
287     <fo:block/>
288   </fo:table-cell>
289 </xsl:template>
290
291 <!-- ==================================================================== -->
292 <xsl:template name="table.frame">
293   <xsl:param name="frame">
294     <xsl:choose>
295       <xsl:when test="../@frame">
296         <xsl:value-of select="../@frame"/>
297       </xsl:when>
298       <xsl:when test="$default.table.frame != ''">
299         <xsl:value-of select="$default.table.frame"/>
300       </xsl:when>
301       <xsl:otherwise>all</xsl:otherwise>
302     </xsl:choose>
303   </xsl:param>
304
305
306   <xsl:choose>
307     <xsl:when test="$frame='all'">
308       <xsl:attribute name="border-start-style">
309         <xsl:value-of select="$table.frame.border.style"/>
310       </xsl:attribute>
311       <xsl:attribute name="border-end-style">
312         <xsl:value-of select="$table.frame.border.style"/>
313       </xsl:attribute>
314       <xsl:attribute name="border-top-style">
315         <xsl:value-of select="$table.frame.border.style"/>
316       </xsl:attribute>
317       <xsl:attribute name="border-bottom-style">
318         <xsl:value-of select="$table.frame.border.style"/>
319       </xsl:attribute>
320       <xsl:attribute name="border-start-width">
321         <xsl:value-of select="$table.frame.border.thickness"/>
322       </xsl:attribute>
323       <xsl:attribute name="border-end-width">
324         <xsl:value-of select="$table.frame.border.thickness"/>
325       </xsl:attribute>
326       <xsl:attribute name="border-top-width">
327         <xsl:value-of select="$table.frame.border.thickness"/>
328       </xsl:attribute>
329       <xsl:attribute name="border-bottom-width">
330         <xsl:value-of select="$table.frame.border.thickness"/>
331       </xsl:attribute>
332       <xsl:attribute name="border-start-color">
333         <xsl:value-of select="$table.frame.border.color"/>
334       </xsl:attribute>
335       <xsl:attribute name="border-end-color">
336         <xsl:value-of select="$table.frame.border.color"/>
337       </xsl:attribute>
338       <xsl:attribute name="border-top-color">
339         <xsl:value-of select="$table.frame.border.color"/>
340       </xsl:attribute>
341       <xsl:attribute name="border-bottom-color">
342         <xsl:value-of select="$table.frame.border.color"/>
343       </xsl:attribute>
344     </xsl:when>
345     <xsl:when test="$frame='bottom'">
346       <xsl:attribute name="border-start-style">none</xsl:attribute>
347       <xsl:attribute name="border-end-style">none</xsl:attribute>
348       <xsl:attribute name="border-top-style">none</xsl:attribute>
349       <xsl:attribute name="border-bottom-style">
350         <xsl:value-of select="$table.frame.border.style"/>
351       </xsl:attribute>
352       <xsl:attribute name="border-bottom-width">
353         <xsl:value-of select="$table.frame.border.thickness"/>
354       </xsl:attribute>
355       <xsl:attribute name="border-bottom-color">
356         <xsl:value-of select="$table.frame.border.color"/>
357       </xsl:attribute>
358     </xsl:when>
359     <xsl:when test="$frame='sides'">
360       <xsl:attribute name="border-start-style">
361         <xsl:value-of select="$table.frame.border.style"/>
362       </xsl:attribute>
363       <xsl:attribute name="border-end-style">
364         <xsl:value-of select="$table.frame.border.style"/>
365       </xsl:attribute>
366       <xsl:attribute name="border-top-style">none</xsl:attribute>
367       <xsl:attribute name="border-bottom-style">none</xsl:attribute>
368       <xsl:attribute name="border-start-width">
369         <xsl:value-of select="$table.frame.border.thickness"/>
370       </xsl:attribute>
371       <xsl:attribute name="border-end-width">
372         <xsl:value-of select="$table.frame.border.thickness"/>
373       </xsl:attribute>
374       <xsl:attribute name="border-start-color">
375         <xsl:value-of select="$table.frame.border.color"/>
376       </xsl:attribute>
377       <xsl:attribute name="border-end-color">
378         <xsl:value-of select="$table.frame.border.color"/>
379       </xsl:attribute>
380     </xsl:when>
381     <xsl:when test="$frame='lhs'">
382       <xsl:attribute name="border-start-style">
383         <xsl:value-of select="$table.frame.border.style"/>
384       </xsl:attribute>
385       <xsl:attribute name="border-end-style">none</xsl:attribute>
386       <xsl:attribute name="border-top-style">none</xsl:attribute>
387       <xsl:attribute name="border-bottom-style">none</xsl:attribute>
388       <xsl:attribute name="border-start-width">
389         <xsl:value-of select="$table.frame.border.thickness"/>
390       </xsl:attribute>
391       <xsl:attribute name="border-start-color">
392         <xsl:value-of select="$table.frame.border.color"/>
393       </xsl:attribute>
394     </xsl:when>
395     <xsl:when test="$frame='rhs'">
396       <xsl:attribute name="border-end-style">
397         <xsl:value-of select="$table.frame.border.style"/>
398       </xsl:attribute>
399       <xsl:attribute name="border-end-style">none</xsl:attribute>
400       <xsl:attribute name="border-top-style">none</xsl:attribute>
401       <xsl:attribute name="border-bottom-style">none</xsl:attribute>
402       <xsl:attribute name="border-end-width">
403         <xsl:value-of select="$table.frame.border.thickness"/>
404       </xsl:attribute>
405       <xsl:attribute name="border-end-color">
406         <xsl:value-of select="$table.frame.border.color"/>
407       </xsl:attribute>
408     </xsl:when>
409     <xsl:when test="$frame='top'">
410       <xsl:attribute name="border-start-style">none</xsl:attribute>
411       <xsl:attribute name="border-end-style">none</xsl:attribute>
412       <xsl:attribute name="border-top-style">
413         <xsl:value-of select="$table.frame.border.style"/>
414       </xsl:attribute>
415       <xsl:attribute name="border-bottom-style">none</xsl:attribute>
416       <xsl:attribute name="border-top-width">
417         <xsl:value-of select="$table.frame.border.thickness"/>
418       </xsl:attribute>
419       <xsl:attribute name="border-top-color">
420         <xsl:value-of select="$table.frame.border.color"/>
421       </xsl:attribute>
422     </xsl:when>
423     <xsl:when test="$frame='topbot'">
424       <xsl:attribute name="border-start-style">none</xsl:attribute>
425       <xsl:attribute name="border-end-style">none</xsl:attribute>
426       <xsl:attribute name="border-top-style">
427         <xsl:value-of select="$table.frame.border.style"/>
428       </xsl:attribute>
429       <xsl:attribute name="border-bottom-style">
430         <xsl:value-of select="$table.frame.border.style"/>
431       </xsl:attribute>
432       <xsl:attribute name="border-top-width">
433         <xsl:value-of select="$table.frame.border.thickness"/>
434       </xsl:attribute>
435       <xsl:attribute name="border-bottom-width">
436         <xsl:value-of select="$table.frame.border.thickness"/>
437       </xsl:attribute>
438       <xsl:attribute name="border-top-color">
439         <xsl:value-of select="$table.frame.border.color"/>
440       </xsl:attribute>
441       <xsl:attribute name="border-bottom-color">
442         <xsl:value-of select="$table.frame.border.color"/>
443       </xsl:attribute>
444     </xsl:when>
445     <xsl:when test="$frame='none'">
446       <xsl:attribute name="border-start-style">none</xsl:attribute>
447       <xsl:attribute name="border-end-style">none</xsl:attribute>
448       <xsl:attribute name="border-top-style">none</xsl:attribute>
449       <xsl:attribute name="border-bottom-style">none</xsl:attribute>
450     </xsl:when>
451     <xsl:otherwise>
452       <xsl:message>
453         <xsl:text>Impossible frame on table: </xsl:text>
454         <xsl:value-of select="$frame"/>
455       </xsl:message>
456       <xsl:attribute name="border-start-style">none</xsl:attribute>
457       <xsl:attribute name="border-end-style">none</xsl:attribute>
458       <xsl:attribute name="border-top-style">none</xsl:attribute>
459       <xsl:attribute name="border-bottom-style">none</xsl:attribute>
460     </xsl:otherwise>
461   </xsl:choose>
462 </xsl:template>
463
464 <!-- ==================================================================== -->
465
466 <xsl:template name="border">
467   <xsl:param name="side" select="'start'"/>
468
469   <xsl:attribute name="border-{$side}-width">
470     <xsl:value-of select="$table.cell.border.thickness"/>
471   </xsl:attribute>
472   <xsl:attribute name="border-{$side}-style">
473     <xsl:value-of select="$table.cell.border.style"/>
474   </xsl:attribute>
475   <xsl:attribute name="border-{$side}-color">
476     <xsl:value-of select="$table.cell.border.color"/>
477   </xsl:attribute>
478 </xsl:template>
479
480 <!-- ==================================================================== -->
481
482 <xsl:template match="d:tgroup" name="tgroup">
483   <xsl:if test="not(@cols) or @cols = '' or string(number(@cols)) = 'NaN'">
484     <xsl:message terminate="yes">
485       <xsl:text>Error: CALS tables must specify the number of columns.</xsl:text>
486     </xsl:message>
487   </xsl:if>
488
489   <xsl:variable name="table.width">
490     <xsl:call-template name="table.width"/>
491   </xsl:variable>
492
493   <xsl:variable name="colspecs">
494     <xsl:choose>
495       <xsl:when test="$use.extensions != 0
496                       and $tablecolumns.extension != 0">
497         <xsl:call-template name="generate.colgroup.raw">
498           <xsl:with-param name="cols" select="@cols"/>
499         </xsl:call-template>
500       </xsl:when>
501       <xsl:otherwise>
502         <xsl:call-template name="generate.colgroup">
503           <xsl:with-param name="cols" select="@cols"/>
504         </xsl:call-template>
505       </xsl:otherwise>
506     </xsl:choose>
507   </xsl:variable>
508
509   <xsl:variable name="prop-columns"
510                 select=".//d:colspec[contains(@colwidth, '*')]"/>
511   <xsl:if test="count($prop-columns) != 0 or
512                 $fop.extensions != 0 or
513                 $fop1.extensions != 0">
514     <xsl:attribute name="table-layout">fixed</xsl:attribute>
515   </xsl:if>
516  
517     <xsl:attribute name="width">
518       <xsl:value-of select="$table.width"/>
519     </xsl:attribute>
520  
521   <xsl:choose>
522     <xsl:when test="$use.extensions != 0
523                     and $tablecolumns.extension != 0">
524       <xsl:choose>
525         <xsl:when test="function-available('stbl:adjustColumnWidths')">
526           <xsl:copy-of select="stbl:adjustColumnWidths($colspecs)"/>
527         </xsl:when>
528         <xsl:when test="function-available('xtbl:adjustColumnWidths')">
529           <xsl:copy-of select="xtbl:adjustColumnWidths($colspecs)"/>
530         </xsl:when>
531         <xsl:when test="function-available('ptbl:adjustColumnWidths')">
532           <xsl:copy-of select="ptbl:adjustColumnWidths($colspecs)"/>
533         </xsl:when>
534         <xsl:otherwise>
535           <xsl:message terminate="yes">
536             <xsl:text>No adjustColumnWidths function available.</xsl:text>
537           </xsl:message>
538         </xsl:otherwise>
539       </xsl:choose>
540     </xsl:when>
541     <xsl:otherwise>
542       <xsl:copy-of select="$colspecs"/>
543     </xsl:otherwise>
544   </xsl:choose>
545
546   <xsl:apply-templates select="d:thead"/>
547   <xsl:apply-templates select="d:tfoot"/>
548   <xsl:apply-templates select="d:tbody"/>
549 </xsl:template>
550
551 <xsl:template match="d:colspec"></xsl:template>
552
553 <xsl:template name="table.width">
554
555   <xsl:variable name="numcols">
556     <xsl:call-template name="widest-html-row">
557       <xsl:with-param name="rows" select=".//d:tr"/>
558     </xsl:call-template>
559   </xsl:variable>
560
561   <xsl:variable name="explicit.table.width">
562     <xsl:choose>
563       <xsl:when test="self::d:entrytbl">
564         <xsl:call-template name="pi.dbfo_table-width"/>
565       </xsl:when>
566       <xsl:when test="self::d:table or self::d:informaltable">
567         <xsl:call-template name="pi.dbfo_table-width"/>
568       </xsl:when>
569       <xsl:otherwise>
570         <!-- * no dbfo@table-width PI as a child of this table, so check -->
571         <!-- * the parent of this table to see if the table has any -->
572         <!-- * sibling dbfo@table-width PIs (FIXME: 2007-07 MikeSmith: we -->
573         <!-- * should really instead be checking here just to see if the -->
574         <!-- * first preceding sibling of this table is a -->
575         <!-- * dbfo@table-width PI) -->
576         <xsl:call-template name="pi.dbfo_table-width">
577           <xsl:with-param name="node" select=".."/>
578         </xsl:call-template>
579       </xsl:otherwise>
580     </xsl:choose>
581   </xsl:variable>
582
583   <xsl:variable name="column.sum">
584     <xsl:choose>
585       <!-- CALS table -->
586       <xsl:when test="d:tgroup/@cols">
587         <!-- change context to the first tgroup -->
588         <xsl:for-each select="d:tgroup[1]">
589           <xsl:if test="count(d:colspec) = @cols">
590             <xsl:for-each select="d:colspec">
591               <xsl:if test="position() != 1">
592                 <xsl:text> + </xsl:text>
593               </xsl:if>
594               <xsl:choose>
595                 <xsl:when test="not(@colwidth)">NOWIDTH</xsl:when>
596                 <xsl:when test="contains(@colwidth, '*')">NOWIDTH</xsl:when>
597                 <xsl:otherwise>
598                   <xsl:value-of select="@colwidth"/>
599                 </xsl:otherwise>
600               </xsl:choose>
601             </xsl:for-each>
602           </xsl:if>
603         </xsl:for-each>
604       </xsl:when>
605       <xsl:otherwise>
606         <!-- HTML table -->
607         <xsl:if test="count(d:col|d:colgroup/d:col) = $numcols">
608           <xsl:for-each select="d:col|d:colgroup/d:col">
609             <xsl:if test="position() != 1">
610               <xsl:text> + </xsl:text>
611             </xsl:if>
612             <xsl:choose>
613               <xsl:when test="not(@width)">NOWIDTH</xsl:when>
614               <xsl:when test="contains(@width, '%')">NOWIDTH</xsl:when>
615               <xsl:otherwise>
616                 <xsl:value-of select="@width"/>
617               </xsl:otherwise>
618             </xsl:choose>
619           </xsl:for-each>
620         </xsl:if>
621       </xsl:otherwise>
622     </xsl:choose>
623   </xsl:variable>
624
625   <xsl:variable name="column.sum.width">
626     <xsl:if test="not(contains($column.sum, 'NOWIDTH'))">
627       <xsl:value-of select="$column.sum"/>
628     </xsl:if>
629   </xsl:variable>
630
631   <xsl:variable name="prop-columns"
632                 select=".//d:colspec[contains(@colwidth, '*')]"/>
633
634   <xsl:variable name="table.width">
635     <xsl:choose>
636       <xsl:when test="$explicit.table.width != ''">
637         <xsl:value-of select="$explicit.table.width"/>
638       </xsl:when>
639       <xsl:when test="$column.sum.width != ''">
640         <xsl:value-of select="$column.sum.width"/>
641       </xsl:when>
642       <xsl:when test="$default.table.width = ''">
643         <xsl:choose>
644           <!-- These processors don't support table-layout="auto" -->
645           <xsl:when test="$fop.extensions != 0 or
646                           $fop1.extensions != 0">
647             <xsl:text>100%</xsl:text>
648           </xsl:when>
649           <!-- Proportional columns imply 100% width -->
650           <xsl:when test="count($prop-columns) != 0">
651             <xsl:text>100%</xsl:text>
652           </xsl:when>
653           <xsl:otherwise>
654             <xsl:text>auto</xsl:text>
655           </xsl:otherwise>
656         </xsl:choose>
657       </xsl:when>
658       <xsl:otherwise>
659         <xsl:value-of select="$default.table.width"/>
660       </xsl:otherwise>
661     </xsl:choose>
662   </xsl:variable>
663   <xsl:value-of select="$table.width"/>
664
665 </xsl:template>
666
667 <xsl:template match="d:spanspec"></xsl:template>
668
669 <xsl:template match="d:thead">
670   <xsl:variable name="tgroup" select="parent::*"/>
671
672   <fo:table-header start-indent="0pt" end-indent="0pt">
673     <xsl:choose>
674       <!-- Use recursion if @morerows is used -->
675       <xsl:when test="d:row/d:entry/@morerows|d:row/d:entrytbl/@morerows">
676         <xsl:apply-templates select="d:row[1]">
677           <xsl:with-param name="spans">
678             <xsl:call-template name="blank.spans">
679               <xsl:with-param name="cols" select="../@cols"/>
680             </xsl:call-template>
681           </xsl:with-param>
682           <xsl:with-param name="browserows" select="'recurse'"/>
683         </xsl:apply-templates>
684       </xsl:when>
685       <xsl:otherwise>
686         <xsl:apply-templates select="d:row">
687           <xsl:with-param name="spans">
688             <xsl:call-template name="blank.spans">
689               <xsl:with-param name="cols" select="../@cols"/>
690             </xsl:call-template>
691           </xsl:with-param>
692           <xsl:with-param name="browserows" select="'loop'" />
693         </xsl:apply-templates>
694       </xsl:otherwise>
695     </xsl:choose>
696   </fo:table-header>
697 </xsl:template>
698
699 <xsl:template match="d:tfoot">
700   <xsl:variable name="tgroup" select="parent::*"/>
701
702   <fo:table-footer start-indent="0pt" end-indent="0pt">
703     <xsl:choose>
704       <!-- Use recursion if @morerows is used -->
705       <xsl:when test="d:row/d:entry/@morerows|d:row/d:entrytbl/@morerows">
706         <xsl:apply-templates select="d:row[1]">
707           <xsl:with-param name="spans">
708             <xsl:call-template name="blank.spans">
709               <xsl:with-param name="cols" select="../@cols"/>
710             </xsl:call-template>
711           </xsl:with-param>
712           <xsl:with-param name="browserows" select="'recurse'"/>
713         </xsl:apply-templates>
714       </xsl:when>
715       <xsl:otherwise>
716         <xsl:apply-templates select="d:row">
717           <xsl:with-param name="spans">
718             <xsl:call-template name="blank.spans">
719               <xsl:with-param name="cols" select="../@cols"/>
720             </xsl:call-template>
721           </xsl:with-param>
722           <xsl:with-param name="browserows" select="'loop'" />
723         </xsl:apply-templates>
724       </xsl:otherwise>
725     </xsl:choose>
726   </fo:table-footer>
727 </xsl:template>
728
729 <xsl:template match="d:tbody">
730   <xsl:variable name="tgroup" select="parent::*"/>
731
732   <fo:table-body start-indent="0pt" end-indent="0pt">
733     <xsl:choose>
734       <!-- Use recursion if @morerows is used -->
735       <xsl:when test="d:row/d:entry/@morerows|d:row/d:entrytbl/@morerows">
736         <xsl:apply-templates select="d:row[1]">
737           <xsl:with-param name="spans">
738             <xsl:call-template name="blank.spans">
739               <xsl:with-param name="cols" select="../@cols"/>
740             </xsl:call-template>
741           </xsl:with-param>
742           <xsl:with-param name="browserows" select="'recurse'"/>
743         </xsl:apply-templates>
744       </xsl:when>
745       <xsl:otherwise>
746         <xsl:apply-templates select="d:row">
747           <xsl:with-param name="spans">
748             <xsl:call-template name="blank.spans">
749               <xsl:with-param name="cols" select="../@cols"/>
750             </xsl:call-template>
751           </xsl:with-param>
752           <xsl:with-param name="browserows" select="'loop'" />
753         </xsl:apply-templates>
754       </xsl:otherwise>
755     </xsl:choose>
756   </fo:table-body>
757 </xsl:template>
758
759 <xsl:template match="d:row">
760   <xsl:param name="spans"/>
761   <xsl:param name="browserows"/>
762
763   <xsl:choose>
764     <xsl:when test="contains($spans, '0')">
765       <xsl:call-template name="normal-row">
766         <xsl:with-param name="spans" select="$spans"/>
767         <xsl:with-param name="browserows" select="$browserows"/>
768       </xsl:call-template>
769     </xsl:when>
770     <xsl:otherwise>
771       <!--
772       <xsl:message>
773         <xsl:text>Ignoring row: </xsl:text>
774         <xsl:value-of select="$spans"/>
775         <xsl:text> = </xsl:text>
776         <xsl:call-template name="consume-row">
777           <xsl:with-param name="spans" select="$spans"/>
778         </xsl:call-template>
779       </xsl:message>
780       -->
781
782       <xsl:if test="normalize-space(.//text()) != ''">
783         <xsl:message>Warning: overlapped row contains content!</xsl:message>
784       </xsl:if>
785
786       <fo:table-row>
787         <xsl:comment> This row intentionally left blank </xsl:comment>
788         <fo:table-cell><fo:block/></fo:table-cell>
789       </fo:table-row>
790
791       <xsl:if test="$browserows = 'recurse'">
792         <xsl:apply-templates select="following-sibling::d:row[1]">
793           <xsl:with-param name="spans">
794             <xsl:call-template name="consume-row">
795               <xsl:with-param name="spans" select="$spans"/>
796             </xsl:call-template>
797           </xsl:with-param>
798           <xsl:with-param name="browserows" select="$browserows"/>
799         </xsl:apply-templates>
800       </xsl:if>
801     </xsl:otherwise>
802   </xsl:choose>
803 </xsl:template>
804
805 <xsl:template name="normal-row">
806   <xsl:param name="spans"/>
807   <xsl:param name="browserows"/>
808
809   <fo:table-row>
810     <xsl:call-template name="table.row.properties"/>
811     <xsl:call-template name="anchor"/>
812
813     <xsl:apply-templates select="(d:entry|d:entrytbl)[1]">
814       <xsl:with-param name="spans" select="$spans"/>
815     </xsl:apply-templates>
816   </fo:table-row>
817
818   <xsl:if test="$browserows = 'recurse'">
819     <xsl:if test="following-sibling::d:row">
820       <xsl:variable name="nextspans">
821         <xsl:apply-templates select="(d:entry|d:entrytbl)[1]" mode="span">
822           <xsl:with-param name="spans" select="$spans"/>
823         </xsl:apply-templates>
824       </xsl:variable>
825   
826       <xsl:apply-templates select="following-sibling::d:row[1]">
827         <xsl:with-param name="spans" select="$nextspans"/>
828         <xsl:with-param name="browserows" select="$browserows"/>
829       </xsl:apply-templates>
830     </xsl:if>
831   </xsl:if>
832 </xsl:template>
833
834 <!-- customize this template to add row properties -->
835 <xsl:template name="table.row.properties">
836
837   <xsl:variable name="row-height">
838     <xsl:if test="processing-instruction('dbfo')">
839       <xsl:call-template name="pi.dbfo_row-height"/>
840     </xsl:if>
841   </xsl:variable>
842
843   <xsl:if test="$row-height != ''">
844     <xsl:attribute name="block-progression-dimension">
845       <xsl:value-of select="$row-height"/>
846     </xsl:attribute>
847   </xsl:if>
848
849   <xsl:variable name="bgcolor">
850     <xsl:call-template name="pi.dbfo_bgcolor"/>
851   </xsl:variable>
852
853   <xsl:if test="$bgcolor != ''">
854     <xsl:attribute name="background-color">
855       <xsl:value-of select="$bgcolor"/>
856     </xsl:attribute>
857   </xsl:if>
858
859   <!-- Keep header row with next row -->
860   <xsl:if test="ancestor::d:thead">
861     <xsl:attribute name="keep-with-next.within-column">always</xsl:attribute>
862   </xsl:if>
863
864 </xsl:template>
865
866 <xsl:template match="d:entry|d:entrytbl" name="entry">
867   <xsl:param name="col" select="1"/>
868   <xsl:param name="spans"/>
869
870   <xsl:variable name="row" select="parent::d:row"/>
871   <xsl:variable name="group" select="$row/parent::*[1]"/>
872   <xsl:variable name="frame" select="ancestor::d:tgroup/parent::*/@frame"/>
873
874   <xsl:variable name="empty.cell" select="count(node()) = 0"/>
875
876   <xsl:variable name="named.colnum">
877     <xsl:call-template name="entry.colnum"/>
878   </xsl:variable>
879
880   <xsl:variable name="entry.colnum">
881     <xsl:choose>
882       <xsl:when test="$named.colnum &gt; 0">
883         <xsl:value-of select="$named.colnum"/>
884       </xsl:when>
885       <xsl:otherwise>
886         <xsl:value-of select="$col"/>
887       </xsl:otherwise>
888     </xsl:choose>
889   </xsl:variable>
890
891   <xsl:variable name="entry.colspan">
892     <xsl:choose>
893       <xsl:when test="@spanname or @namest">
894         <xsl:call-template name="calculate.colspan"/>
895       </xsl:when>
896       <xsl:otherwise>1</xsl:otherwise>
897     </xsl:choose>
898   </xsl:variable>
899
900   <xsl:variable name="following.spans">
901     <xsl:call-template name="calculate.following.spans">
902       <xsl:with-param name="colspan" select="$entry.colspan"/>
903       <xsl:with-param name="spans" select="$spans"/>
904     </xsl:call-template>
905   </xsl:variable>
906
907   <xsl:variable name="rowsep">
908     <xsl:choose>
909       <!-- If this is the last row, rowsep never applies (except when 
910            the ancestor tgroup has a following sibling tgroup) -->
911       <xsl:when test="not(ancestor-or-self::d:row[1]/following-sibling::d:row
912                           or ancestor-or-self::d:thead/following-sibling::d:tbody
913                           or ancestor-or-self::d:tbody/preceding-sibling::d:tfoot)
914                           and not(ancestor::d:tgroup/following-sibling::d:tgroup)">
915         <xsl:value-of select="0"/>
916       </xsl:when>
917       <!-- Check for morerows too -->
918       <xsl:when test="(@morerows and count(ancestor-or-self::d:row[1]/
919                        following-sibling::d:row) = @morerows )
920                       and not (ancestor-or-self::d:thead/following-sibling::d:tbody
921                        or ancestor-or-self::d:tbody/preceding-sibling::d:tfoot)
922                        and not(ancestor::d:tgroup/following-sibling::d:tgroup)">
923         <xsl:value-of select="0"/>
924       </xsl:when>
925
926       <xsl:otherwise>
927         <xsl:call-template name="inherited.table.attribute">
928           <xsl:with-param name="entry" select="."/>
929           <xsl:with-param name="colnum" select="$entry.colnum"/>
930           <xsl:with-param name="attribute" select="'rowsep'"/>
931         </xsl:call-template>
932       </xsl:otherwise>
933     </xsl:choose>
934   </xsl:variable>
935
936 <!--
937   <xsl:message><xsl:value-of select="."/>: <xsl:value-of select="$rowsep"/></xsl:message>
938 -->
939
940   <xsl:variable name="colsep">
941     <xsl:choose>
942       <!-- If this is the last column, colsep never applies. -->
943       <xsl:when test="$following.spans = ''">0</xsl:when>
944       <xsl:otherwise>
945         <xsl:call-template name="inherited.table.attribute">
946           <xsl:with-param name="entry" select="."/>
947           <xsl:with-param name="colnum" select="$entry.colnum"/>
948           <xsl:with-param name="attribute" select="'colsep'"/>
949         </xsl:call-template>
950       </xsl:otherwise>
951     </xsl:choose>
952   </xsl:variable>
953
954   <xsl:variable name="valign">
955     <xsl:call-template name="inherited.table.attribute">
956       <xsl:with-param name="entry" select="."/>
957       <xsl:with-param name="colnum" select="$entry.colnum"/>
958       <xsl:with-param name="attribute" select="'valign'"/>
959     </xsl:call-template>
960   </xsl:variable>
961
962   <xsl:variable name="align">
963     <xsl:call-template name="inherited.table.attribute">
964       <xsl:with-param name="entry" select="."/>
965       <xsl:with-param name="colnum" select="$entry.colnum"/>
966       <xsl:with-param name="attribute" select="'align'"/>
967     </xsl:call-template>
968   </xsl:variable>
969
970   <xsl:variable name="char">
971     <xsl:call-template name="inherited.table.attribute">
972       <xsl:with-param name="entry" select="."/>
973       <xsl:with-param name="colnum" select="$entry.colnum"/>
974       <xsl:with-param name="attribute" select="'char'"/>
975     </xsl:call-template>
976   </xsl:variable>
977
978   <xsl:variable name="charoff">
979     <xsl:call-template name="inherited.table.attribute">
980       <xsl:with-param name="entry" select="."/>
981       <xsl:with-param name="colnum" select="$entry.colnum"/>
982       <xsl:with-param name="attribute" select="'charoff'"/>
983     </xsl:call-template>
984   </xsl:variable>
985
986   <xsl:choose>
987     <xsl:when test="$spans != '' and not(starts-with($spans,'0:'))">
988       <xsl:call-template name="entry">
989         <xsl:with-param name="col" select="$col+1"/>
990         <xsl:with-param name="spans" select="substring-after($spans,':')"/>
991       </xsl:call-template>
992     </xsl:when>
993
994     <xsl:when test="number($entry.colnum) &gt; $col">
995       <xsl:call-template name="empty.table.cell">
996         <xsl:with-param name="colnum" select="$col"/>
997       </xsl:call-template>
998       <xsl:call-template name="entry">
999         <xsl:with-param name="col" select="$col+1"/>
1000         <xsl:with-param name="spans" select="substring-after($spans,':')"/>
1001       </xsl:call-template>
1002     </xsl:when>
1003
1004     <xsl:otherwise>
1005       <xsl:variable name="cell.content">
1006         <fo:block>
1007           <xsl:call-template name="table.cell.block.properties"/>
1008
1009           <!-- are we missing any indexterms? -->
1010           <xsl:if test="not(preceding-sibling::d:entry)
1011                         and not(parent::d:row/preceding-sibling::d:row)">
1012             <!-- this is the first entry of the first row -->
1013             <xsl:if test="ancestor::d:thead or
1014                           (ancestor::d:tbody
1015                            and not(ancestor::d:tbody/preceding-sibling::d:thead
1016                                    or ancestor::d:tbody/preceding-sibling::d:tbody))">
1017               <!-- of the thead or the first tbody -->
1018               <xsl:apply-templates select="ancestor::d:tgroup/preceding-sibling::d:indexterm"/>
1019             </xsl:if>
1020           </xsl:if>
1021
1022           <!--
1023           <xsl:text>(</xsl:text>
1024           <xsl:value-of select="$rowsep"/>
1025           <xsl:text>,</xsl:text>
1026           <xsl:value-of select="$colsep"/>
1027           <xsl:text>)</xsl:text>
1028           -->
1029           <xsl:choose>
1030             <xsl:when test="$empty.cell">
1031               <xsl:text>&#160;</xsl:text>
1032             </xsl:when>
1033             <xsl:when test="self::d:entrytbl">
1034               <xsl:variable name="prop-columns"
1035                             select=".//d:colspec[contains(@colwidth, '*')]"/>
1036               <fo:table xsl:use-attribute-sets="table.table.properties">
1037                 <xsl:if test="count($prop-columns) != 0">
1038                   <xsl:attribute name="table-layout">fixed</xsl:attribute>
1039                 </xsl:if>
1040                 <xsl:call-template name="tgroup"/>
1041               </fo:table>
1042             </xsl:when>
1043             <xsl:otherwise>
1044               <xsl:apply-templates/>
1045             </xsl:otherwise>
1046           </xsl:choose>
1047         </fo:block>
1048       </xsl:variable>
1049
1050       <xsl:variable name="cell-orientation">
1051         <xsl:call-template name="pi.dbfo_orientation">
1052           <xsl:with-param name="node" select="ancestor-or-self::d:entry"/>
1053         </xsl:call-template>
1054       </xsl:variable>
1055
1056       <xsl:variable name="row-orientation">
1057         <xsl:call-template name="pi.dbfo_orientation">
1058           <xsl:with-param name="node" select="ancestor-or-self::d:row"/>
1059         </xsl:call-template>
1060       </xsl:variable>
1061
1062       <xsl:variable name="cell-width">
1063         <xsl:call-template name="pi.dbfo_rotated-width">
1064           <xsl:with-param name="node" select="ancestor-or-self::d:entry"/>
1065         </xsl:call-template>
1066       </xsl:variable>
1067
1068       <xsl:variable name="row-width">
1069         <xsl:call-template name="pi.dbfo_rotated-width">
1070           <xsl:with-param name="node" select="ancestor-or-self::d:row"/>
1071         </xsl:call-template>
1072       </xsl:variable>
1073
1074       <xsl:variable name="orientation">
1075         <xsl:choose>
1076           <xsl:when test="$cell-orientation != ''">
1077             <xsl:value-of select="$cell-orientation"/>
1078           </xsl:when>
1079           <xsl:otherwise>
1080             <xsl:value-of select="$row-orientation"/>
1081           </xsl:otherwise>
1082         </xsl:choose>
1083       </xsl:variable>
1084
1085       <xsl:variable name="rotated-width">
1086         <xsl:choose>
1087           <xsl:when test="$cell-width != ''">
1088             <xsl:value-of select="$cell-width"/>
1089           </xsl:when>
1090           <xsl:otherwise>
1091             <xsl:value-of select="$row-width"/>
1092           </xsl:otherwise>
1093         </xsl:choose>
1094       </xsl:variable>
1095
1096       <xsl:variable name="bgcolor">
1097         <xsl:call-template name="pi.dbfo_bgcolor">
1098           <xsl:with-param name="node" select="ancestor-or-self::d:entry"/>
1099         </xsl:call-template>
1100       </xsl:variable>
1101
1102       <fo:table-cell xsl:use-attribute-sets="table.cell.padding">
1103         <xsl:call-template name="table.cell.properties">
1104           <xsl:with-param name="bgcolor.pi" select="$bgcolor"/>
1105           <xsl:with-param name="rowsep.inherit" select="$rowsep"/>
1106           <xsl:with-param name="colsep.inherit" select="$colsep"/>
1107           <xsl:with-param name="col" select="$col"/>
1108           <xsl:with-param name="valign.inherit" select="$valign"/>
1109           <xsl:with-param name="align.inherit" select="$align"/>
1110           <xsl:with-param name="char.inherit" select="$char"/>
1111         </xsl:call-template>
1112
1113         <xsl:call-template name="anchor"/>
1114
1115         <xsl:if test="@morerows">
1116           <xsl:attribute name="number-rows-spanned">
1117             <xsl:value-of select="@morerows+1"/>
1118           </xsl:attribute>
1119         </xsl:if>
1120
1121         <xsl:if test="$entry.colspan &gt; 1">
1122           <xsl:attribute name="number-columns-spanned">
1123             <xsl:value-of select="$entry.colspan"/>
1124           </xsl:attribute>
1125         </xsl:if>
1126
1127 <!--
1128         <xsl:if test="@charoff">
1129           <xsl:attribute name="charoff">
1130             <xsl:value-of select="@charoff"/>
1131           </xsl:attribute>
1132         </xsl:if>
1133 -->
1134
1135         <xsl:choose>
1136           <xsl:when test="$fop.extensions = 0
1137                           and $orientation != ''">
1138             <fo:block-container reference-orientation="{$orientation}">
1139               <xsl:if test="$rotated-width != ''">
1140                 <xsl:attribute name="width">
1141                   <xsl:value-of select="$rotated-width"/>
1142                 </xsl:attribute>
1143               </xsl:if>
1144               <xsl:copy-of select="$cell.content"/>
1145             </fo:block-container>
1146           </xsl:when>
1147           <xsl:otherwise>
1148             <xsl:copy-of select="$cell.content"/>
1149           </xsl:otherwise>
1150         </xsl:choose>
1151       </fo:table-cell>
1152
1153       <xsl:choose>
1154         <xsl:when test="following-sibling::d:entry|following-sibling::d:entrytbl">
1155           <xsl:apply-templates select="(following-sibling::d:entry
1156                                        |following-sibling::d:entrytbl)[1]">
1157             <xsl:with-param name="col" select="$col+$entry.colspan"/>
1158             <xsl:with-param name="spans" select="$following.spans"/>
1159           </xsl:apply-templates>
1160         </xsl:when>
1161         <xsl:otherwise>
1162           <xsl:call-template name="finaltd">
1163             <xsl:with-param name="spans" select="$following.spans"/>
1164             <xsl:with-param name="col" select="$col+$entry.colspan"/>
1165           </xsl:call-template>
1166         </xsl:otherwise>
1167       </xsl:choose>
1168     </xsl:otherwise>
1169   </xsl:choose>
1170 </xsl:template>
1171
1172 <!-- Expand this template to add properties to any fo:table-cell -->
1173 <xsl:template name="table.cell.properties">
1174   <xsl:param name="bgcolor.pi" select="''"/>
1175   <xsl:param name="rowsep.inherit" select="1"/>
1176   <xsl:param name="colsep.inherit" select="1"/>
1177   <xsl:param name="col" select="1"/>
1178   <xsl:param name="valign.inherit" select="''"/>
1179   <xsl:param name="align.inherit" select="''"/>
1180   <xsl:param name="char.inherit" select="''"/>
1181
1182   <xsl:choose>
1183     <xsl:when test="ancestor::d:tgroup">
1184       <xsl:if test="$bgcolor.pi != ''">
1185         <xsl:attribute name="background-color">
1186           <xsl:value-of select="$bgcolor.pi"/>
1187         </xsl:attribute>
1188       </xsl:if>
1189
1190       <xsl:if test="$rowsep.inherit &gt; 0">
1191         <xsl:call-template name="border">
1192           <xsl:with-param name="side" select="'bottom'"/>
1193         </xsl:call-template>
1194       </xsl:if>
1195
1196       <xsl:if test="$colsep.inherit &gt; 0 and 
1197                       $col &lt; (ancestor::d:tgroup/@cols|ancestor::d:entrytbl/@cols)[last()]">
1198         <xsl:call-template name="border">
1199           <xsl:with-param name="side" select="'end'"/>
1200         </xsl:call-template>
1201       </xsl:if>
1202
1203       <xsl:if test="$valign.inherit != ''">
1204         <xsl:attribute name="display-align">
1205           <xsl:choose>
1206             <xsl:when test="$valign.inherit='top'">before</xsl:when>
1207             <xsl:when test="$valign.inherit='middle'">center</xsl:when>
1208             <xsl:when test="$valign.inherit='bottom'">after</xsl:when>
1209             <xsl:otherwise>
1210               <xsl:message>
1211                 <xsl:text>Unexpected valign value: </xsl:text>
1212                 <xsl:value-of select="$valign.inherit"/>
1213                 <xsl:text>, center used.</xsl:text>
1214               </xsl:message>
1215               <xsl:text>center</xsl:text>
1216             </xsl:otherwise>
1217           </xsl:choose>
1218         </xsl:attribute>
1219       </xsl:if>
1220
1221       <xsl:choose>
1222         <xsl:when test="$align.inherit = 'char' and $char.inherit != ''">
1223           <xsl:attribute name="text-align">
1224             <xsl:value-of select="$char.inherit"/>
1225           </xsl:attribute>
1226         </xsl:when>
1227         <xsl:when test="$align.inherit != ''">
1228           <xsl:attribute name="text-align">
1229             <xsl:value-of select="$align.inherit"/>
1230           </xsl:attribute>
1231         </xsl:when>
1232       </xsl:choose>
1233
1234     </xsl:when>
1235     <xsl:otherwise>
1236       <!-- HTML table -->
1237       <xsl:if test="$bgcolor.pi != ''">
1238         <xsl:attribute name="background-color">
1239           <xsl:value-of select="$bgcolor.pi"/>
1240         </xsl:attribute>
1241       </xsl:if>
1242
1243       <xsl:if test="$align.inherit != ''">
1244         <xsl:attribute name="text-align">
1245           <xsl:value-of select="$align.inherit"/>
1246         </xsl:attribute>
1247       </xsl:if>
1248
1249       <xsl:if test="$valign.inherit != ''">
1250         <xsl:attribute name="display-align">
1251           <xsl:choose>
1252             <xsl:when test="$valign.inherit='top'">before</xsl:when>
1253             <xsl:when test="$valign.inherit='middle'">center</xsl:when>
1254             <xsl:when test="$valign.inherit='bottom'">after</xsl:when>
1255             <xsl:otherwise>
1256               <xsl:message>
1257                 <xsl:text>Unexpected valign value: </xsl:text>
1258                 <xsl:value-of select="$valign.inherit"/>
1259                 <xsl:text>, center used.</xsl:text>
1260               </xsl:message>
1261               <xsl:text>center</xsl:text>
1262             </xsl:otherwise>
1263           </xsl:choose>
1264         </xsl:attribute>
1265       </xsl:if>
1266
1267       <xsl:call-template name="html.table.cell.rules"/>
1268
1269     </xsl:otherwise>
1270   </xsl:choose>
1271
1272 </xsl:template>
1273
1274 <!-- Expand this template to add properties to any cell's block -->
1275 <xsl:template name="table.cell.block.properties">
1276   <!-- highlight this entry? -->
1277   <xsl:choose>
1278     <xsl:when test="ancestor::d:thead or ancestor::d:tfoot">
1279       <xsl:attribute name="font-weight">bold</xsl:attribute>
1280     </xsl:when>
1281     <!-- Make row headers bold too -->
1282     <xsl:when test="ancestor::d:tbody and
1283                     (ancestor::d:table[@rowheader = 'firstcol'] or
1284                     ancestor::d:informaltable[@rowheader = 'firstcol']) and
1285                     ancestor-or-self::d:entry[1][count(preceding-sibling::d:entry) = 0]">
1286       <xsl:attribute name="font-weight">bold</xsl:attribute>
1287     </xsl:when>
1288   </xsl:choose>
1289 </xsl:template>
1290
1291 <xsl:template match="d:entry|d:entrytbl" name="sentry" mode="span">
1292   <xsl:param name="col" select="1"/>
1293   <xsl:param name="spans"/>
1294
1295   <xsl:variable name="entry.colnum">
1296     <xsl:call-template name="entry.colnum"/>
1297   </xsl:variable>
1298
1299   <xsl:variable name="entry.colspan">
1300     <xsl:choose>
1301       <xsl:when test="@spanname or @namest">
1302         <xsl:call-template name="calculate.colspan"/>
1303       </xsl:when>
1304       <xsl:otherwise>1</xsl:otherwise>
1305     </xsl:choose>
1306   </xsl:variable>
1307
1308   <xsl:variable name="following.spans">
1309     <xsl:call-template name="calculate.following.spans">
1310       <xsl:with-param name="colspan" select="$entry.colspan"/>
1311       <xsl:with-param name="spans" select="$spans"/>
1312     </xsl:call-template>
1313   </xsl:variable>
1314
1315   <xsl:choose>
1316     <xsl:when test="$spans != '' and not(starts-with($spans,'0:'))">
1317       <xsl:value-of select="substring-before($spans,':')-1"/>
1318       <xsl:text>:</xsl:text>
1319       <xsl:call-template name="sentry">
1320         <xsl:with-param name="col" select="$col+1"/>
1321         <xsl:with-param name="spans" select="substring-after($spans,':')"/>
1322       </xsl:call-template>
1323     </xsl:when>
1324
1325     <xsl:when test="number($entry.colnum) &gt; $col">
1326       <xsl:text>0:</xsl:text>
1327       <xsl:call-template name="sentry">
1328         <xsl:with-param name="col" select="$col + 1"/>
1329         <xsl:with-param name="spans" select="substring-after($spans,':')"/>
1330       </xsl:call-template>
1331     </xsl:when>
1332
1333     <xsl:otherwise>
1334       <xsl:call-template name="copy-string">
1335         <xsl:with-param name="count" select="$entry.colspan"/>
1336         <xsl:with-param name="string">
1337           <xsl:choose>
1338             <xsl:when test="@morerows">
1339               <xsl:value-of select="@morerows"/>
1340             </xsl:when>
1341             <xsl:otherwise>0</xsl:otherwise>
1342           </xsl:choose>
1343           <xsl:text>:</xsl:text>
1344         </xsl:with-param>
1345       </xsl:call-template>
1346
1347       <xsl:choose>
1348         <xsl:when test="following-sibling::d:entry|following-sibling::d:entrytbl">
1349           <xsl:apply-templates select="(following-sibling::d:entry
1350                                        |following-sibling::d:entrytbl)[1]"
1351                                mode="span">
1352             <xsl:with-param name="col" select="$col+$entry.colspan"/>
1353             <xsl:with-param name="spans" select="$following.spans"/>
1354           </xsl:apply-templates>
1355         </xsl:when>
1356         <xsl:otherwise>
1357           <xsl:call-template name="sfinaltd">
1358             <xsl:with-param name="spans" select="$following.spans"/>
1359           </xsl:call-template>
1360         </xsl:otherwise>
1361       </xsl:choose>
1362     </xsl:otherwise>
1363   </xsl:choose>
1364 </xsl:template>
1365
1366 <xsl:template name="generate.colgroup.raw">
1367   <xsl:param name="cols" select="1"/>
1368   <xsl:param name="count" select="1"/>
1369
1370   <xsl:choose>
1371     <xsl:when test="$count>$cols"></xsl:when>
1372     <xsl:otherwise>
1373       <xsl:call-template name="generate.col.raw">
1374         <xsl:with-param name="countcol" select="$count"/>
1375       </xsl:call-template>
1376       <xsl:call-template name="generate.colgroup.raw">
1377         <xsl:with-param name="cols" select="$cols"/>
1378         <xsl:with-param name="count" select="$count+1"/>
1379       </xsl:call-template>
1380     </xsl:otherwise>
1381   </xsl:choose>
1382 </xsl:template>
1383
1384 <xsl:template name="generate.colgroup">
1385   <xsl:param name="cols" select="1"/>
1386   <xsl:param name="count" select="1"/>
1387
1388   <xsl:choose>
1389     <xsl:when test="$count>$cols"></xsl:when>
1390     <xsl:otherwise>
1391       <xsl:call-template name="generate.col">
1392         <xsl:with-param name="countcol" select="$count"/>
1393       </xsl:call-template>
1394       <xsl:call-template name="generate.colgroup">
1395         <xsl:with-param name="cols" select="$cols"/>
1396         <xsl:with-param name="count" select="$count+1"/>
1397       </xsl:call-template>
1398     </xsl:otherwise>
1399   </xsl:choose>
1400 </xsl:template>
1401
1402 <xsl:template name="generate.col.raw">
1403   <!-- generate the table-column for column countcol -->
1404   <xsl:param name="countcol">1</xsl:param>
1405   <xsl:param name="colspecs" select="./d:colspec"/>
1406   <xsl:param name="count">1</xsl:param>
1407   <xsl:param name="colnum">1</xsl:param>
1408
1409   <xsl:choose>
1410     <xsl:when test="$count>count($colspecs)">
1411       <fo:table-column column-number="{$countcol}"/>
1412     </xsl:when>
1413     <xsl:otherwise>
1414       <xsl:variable name="colspec" select="$colspecs[$count=position()]"/>
1415
1416       <xsl:variable name="colspec.colnum">
1417         <xsl:choose>
1418           <xsl:when test="$colspec/@colnum">
1419             <xsl:value-of select="$colspec/@colnum"/>
1420           </xsl:when>
1421           <xsl:otherwise>
1422             <xsl:value-of select="$colnum"/>
1423           </xsl:otherwise>
1424         </xsl:choose>
1425       </xsl:variable>
1426
1427       <xsl:variable name="colspec.colwidth">
1428         <xsl:choose>
1429           <xsl:when test="normalize-space($colspec/@colwidth)='*'">1*</xsl:when>
1430           <xsl:when test="$colspec/@colwidth">
1431             <xsl:value-of select="$colspec/@colwidth"/>
1432           </xsl:when>
1433           <xsl:otherwise>1*</xsl:otherwise>
1434         </xsl:choose>
1435       </xsl:variable>
1436
1437       <xsl:choose>
1438         <xsl:when test="$colspec.colnum=$countcol">
1439           <fo:table-column column-number="{$countcol}">
1440             <xsl:attribute name="column-width">
1441               <xsl:value-of select="$colspec.colwidth"/>
1442             </xsl:attribute>
1443           </fo:table-column>
1444         </xsl:when>
1445         <xsl:otherwise>
1446           <xsl:call-template name="generate.col.raw">
1447             <xsl:with-param name="countcol" select="$countcol"/>
1448             <xsl:with-param name="colspecs" select="$colspecs"/>
1449             <xsl:with-param name="count" select="$count+1"/>
1450             <xsl:with-param name="colnum">
1451               <xsl:choose>
1452                 <xsl:when test="$colspec/@colnum">
1453                   <xsl:value-of select="$colspec/@colnum + 1"/>
1454                 </xsl:when>
1455                 <xsl:otherwise>
1456                   <xsl:value-of select="$colnum + 1"/>
1457                 </xsl:otherwise>
1458               </xsl:choose>
1459             </xsl:with-param>
1460            </xsl:call-template>
1461         </xsl:otherwise>
1462       </xsl:choose>
1463     </xsl:otherwise>
1464   </xsl:choose>
1465 </xsl:template>
1466
1467 <xsl:template name="generate.col">
1468   <!-- generate the table-column for column countcol -->
1469   <xsl:param name="countcol">1</xsl:param>
1470   <xsl:param name="colspecs" select="./d:colspec"/>
1471   <xsl:param name="count">1</xsl:param>
1472   <xsl:param name="colnum">1</xsl:param>
1473
1474   <xsl:choose>
1475     <xsl:when test="$count>count($colspecs)">
1476       <fo:table-column column-number="{$countcol}">
1477         <xsl:variable name="colwidth">
1478           <xsl:call-template name="calc.column.width"/>
1479         </xsl:variable>
1480           <xsl:attribute name="column-width">
1481             <xsl:value-of select="$colwidth"/>
1482           </xsl:attribute>
1483       </fo:table-column>
1484     </xsl:when>
1485     <xsl:otherwise>
1486       <xsl:variable name="colspec" select="$colspecs[$count=position()]"/>
1487
1488       <xsl:variable name="colspec.colnum">
1489         <xsl:choose>
1490           <xsl:when test="$colspec/@colnum">
1491             <xsl:value-of select="$colspec/@colnum"/>
1492           </xsl:when>
1493           <xsl:otherwise>
1494             <xsl:value-of select="$colnum"/>
1495           </xsl:otherwise>
1496         </xsl:choose>
1497       </xsl:variable>
1498
1499       <xsl:variable name="colspec.colwidth">
1500         <xsl:choose>
1501           <xsl:when test="$colspec/@colwidth">
1502             <xsl:value-of select="$colspec/@colwidth"/>
1503           </xsl:when>
1504           <xsl:otherwise>1*</xsl:otherwise>
1505         </xsl:choose>
1506       </xsl:variable>
1507
1508       <xsl:choose>
1509         <xsl:when test="$colspec.colnum=$countcol">
1510           <fo:table-column column-number="{$countcol}">
1511             <xsl:variable name="colwidth">
1512               <xsl:call-template name="calc.column.width">
1513                 <xsl:with-param name="colwidth">
1514                   <xsl:value-of select="$colspec.colwidth"/>
1515                 </xsl:with-param>
1516               </xsl:call-template>
1517             </xsl:variable>
1518               <xsl:attribute name="column-width">
1519                 <xsl:value-of select="$colwidth"/>
1520               </xsl:attribute>
1521           </fo:table-column>
1522         </xsl:when>
1523         <xsl:otherwise>
1524           <xsl:call-template name="generate.col">
1525             <xsl:with-param name="countcol" select="$countcol"/>
1526             <xsl:with-param name="colspecs" select="$colspecs"/>
1527             <xsl:with-param name="count" select="$count+1"/>
1528             <xsl:with-param name="colnum">
1529               <xsl:choose>
1530                 <xsl:when test="$colspec/@colnum">
1531                   <xsl:value-of select="$colspec/@colnum + 1"/>
1532                 </xsl:when>
1533                 <xsl:otherwise>
1534                   <xsl:value-of select="$colnum + 1"/>
1535                 </xsl:otherwise>
1536               </xsl:choose>
1537             </xsl:with-param>
1538            </xsl:call-template>
1539         </xsl:otherwise>
1540       </xsl:choose>
1541     </xsl:otherwise>
1542   </xsl:choose>
1543 </xsl:template>
1544
1545 <doc:template name="calc.column.width" xmlns="">
1546 <refpurpose>Calculate an XSL FO table column width specification from a
1547 CALS table column width specification.</refpurpose>
1548
1549 <refdescription>
1550 <para>CALS expresses table column widths in the following basic
1551 forms:</para>
1552
1553 <itemizedlist>
1554 <listitem>
1555 <para><emphasis>99.99units</emphasis>, a fixed length specifier.</para>
1556 </listitem>
1557 <listitem>
1558 <para><emphasis>99.99</emphasis>, a fixed length specifier without any units.</para>
1559 </listitem>
1560 <listitem>
1561 <para><emphasis>99.99*</emphasis>, a relative length specifier.</para>
1562 </listitem>
1563 <listitem>
1564 <para><emphasis>99.99*+99.99units</emphasis>, a combination of both.</para>
1565 </listitem>
1566 </itemizedlist>
1567
1568 <para>The CALS units are points (pt), picas (pi), centimeters (cm),
1569 millimeters (mm), and inches (in). These are the same units as XSL,
1570 except that XSL abbreviates picas "pc" instead of "pi". If a length
1571 specifier has no units, the CALS default unit (pt) is assumed.</para>
1572
1573 <para>Relative length specifiers are represented in XSL with the
1574 proportional-column-width() function.</para>
1575
1576 <para>Here are some examples:</para>
1577
1578 <itemizedlist>
1579 <listitem>
1580 <para>"36pt" becomes "36pt"</para>
1581 </listitem>
1582 <listitem>
1583 <para>"3pi" becomes "3pc"</para>
1584 </listitem>
1585 <listitem>
1586 <para>"36" becomes "36pt"</para>
1587 </listitem>
1588 <listitem>
1589 <para>"3*" becomes "proportional-column-width(3)"</para>
1590 </listitem>
1591 <listitem>
1592 <para>"3*+2pi" becomes "proportional-column-width(3)+2pc"</para>
1593 </listitem>
1594 <listitem>
1595 <para>"1*+2" becomes "proportional-column-width(1)+2pt"</para>
1596 </listitem>
1597 </itemizedlist>
1598 </refdescription>
1599
1600 <refparameter>
1601 <variablelist>
1602 <varlistentry><term>colwidth</term>
1603 <listitem>
1604 <para>The CALS column width specification.</para>
1605 </listitem>
1606 </varlistentry>
1607 </variablelist>
1608 </refparameter>
1609
1610 <refreturn>
1611 <para>The XSL column width specification.</para>
1612 </refreturn>
1613 </doc:template>
1614
1615 <xsl:template name="calc.column.width">
1616   <xsl:param name="colwidth">1*</xsl:param>
1617
1618   <!-- Ok, the colwidth could have any one of the following forms: -->
1619   <!--        1*       = proportional width -->
1620   <!--         *       = same as 1* -->
1621   <!--     1unit       = 1.0 units wide -->
1622   <!--         1       = 1pt wide -->
1623   <!--  1*+1unit       = proportional width + some fixed width -->
1624   <!--      1*+1       = proportional width + some fixed width -->
1625
1626   <!-- If it has a proportional width, translate it to XSL -->
1627   <xsl:if test="contains($colwidth, '*')">
1628     <xsl:text>proportional-column-width(</xsl:text>
1629     <xsl:choose>
1630       <xsl:when test="substring-before($colwidth, '*') != ''"> 
1631         <xsl:value-of select="substring-before($colwidth, '*')"/>
1632       </xsl:when>
1633       <xsl:otherwise>
1634          <xsl:text>1.00</xsl:text>
1635       </xsl:otherwise>
1636     </xsl:choose>
1637     <xsl:text>)</xsl:text>
1638   </xsl:if>
1639
1640   <!-- Now grab the non-proportional part of the specification -->
1641   <xsl:variable name="width-units">
1642     <xsl:choose>
1643       <xsl:when test="contains($colwidth, '*')">
1644         <xsl:value-of
1645              select="normalize-space(substring-after($colwidth, '*'))"/>
1646       </xsl:when>
1647       <xsl:otherwise>
1648         <xsl:value-of select="normalize-space($colwidth)"/>
1649       </xsl:otherwise>
1650     </xsl:choose>
1651   </xsl:variable>
1652
1653   <!-- Ok, now the width-units could have any one of the following forms: -->
1654   <!--                 = <empty string> -->
1655   <!--     1unit       = 1.0 units wide -->
1656   <!--         1       = 1pt wide -->
1657   <!-- with an optional leading sign -->
1658
1659   <!-- Grab the width part by blanking out the units part and discarding -->
1660   <!-- whitespace. It's not pretty, but it works. -->
1661   <xsl:variable name="width"
1662        select="normalize-space(translate($width-units,
1663                                          '+-0123456789.abcdefghijklmnopqrstuvwxyz',
1664                                          '+-0123456789.'))"/>
1665
1666   <!-- Grab the units part by blanking out the width part and discarding -->
1667   <!-- whitespace. It's not pretty, but it works. -->
1668   <xsl:variable name="units"
1669        select="normalize-space(translate($width-units,
1670                                          'abcdefghijklmnopqrstuvwxyz+-0123456789.',
1671                                          'abcdefghijklmnopqrstuvwxyz'))"/>
1672
1673   <!-- Output the width -->
1674   <xsl:value-of select="$width"/>
1675
1676   <!-- Output the units, translated appropriately -->
1677   <xsl:choose>
1678     <xsl:when test="$units = 'pi'">pc</xsl:when>
1679     <xsl:when test="$units = '' and $width != ''">pt</xsl:when>
1680     <xsl:otherwise><xsl:value-of select="$units"/></xsl:otherwise>
1681   </xsl:choose>
1682 </xsl:template>
1683
1684 <xsl:template match="d:table/d:caption">
1685   <fo:block xsl:use-attribute-sets="table.caption.properties">
1686     <xsl:apply-templates/>
1687   </fo:block>
1688 </xsl:template>
1689
1690 <!-- ==================================================================== -->
1691
1692 </xsl:stylesheet>