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