2 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
3 xmlns:exsl="http://exslt.org/common"
4 xmlns:dyn="http://exslt.org/dynamic"
5 xmlns:saxon="http://icl.com/saxon"
6 exclude-result-prefixes="exsl dyn saxon"
9 <!-- ********************************************************************
10 $Id: utility.xsl 8236 2009-02-09 17:44:52Z xmldoc $
11 ********************************************************************
13 This file is part of the XSL DocBook Stylesheet distribution.
14 See ../README or http://docbook.sf.net/release/xsl/current/ for
15 copyright and other information.
17 ******************************************************************** -->
19 <!-- ==================================================================== -->
21 <!-- * This file contains "utility" templates that are called multiple -->
22 <!-- * times per each Refentry. -->
24 <!-- ==================================================================== -->
26 <!-- * NOTE TO DEVELOPERS: For ease of maintenance, the current -->
27 <!-- * manpages stylesheets use the "bold" and "italic" named -->
28 <!-- * templates for anything and everything that needs to get -->
29 <!-- * boldfaced or italicized. -->
31 <!-- * So if you add anything that needs bold or italic character -->
32 <!-- * formatting, try to apply these templates to it rather than -->
33 <!-- * writing separate code to format it. This can be a little odd if -->
34 <!-- * the content you want to format is not element content; in those -->
35 <!-- * cases, you need to turn it into element content before applying -->
36 <!-- * the template; see examples of this in the existing code. -->
38 <xsl:template name="bold">
39 <xsl:param name="node"/>
40 <xsl:param name="context"/>
42 <xsl:when test="not($context[ancestor::title])">
43 <xsl:for-each select="$node/node()">
44 <xsl:text>\fB</xsl:text>
45 <xsl:apply-templates select="."/>
46 <xsl:text>\fR</xsl:text>
50 <xsl:apply-templates select="$node/node()"/>
55 <xsl:template name="italic">
56 <xsl:param name="node"/>
57 <xsl:param name="context"/>
58 <xsl:for-each select="$node/node()">
59 <xsl:text>\fI</xsl:text>
60 <xsl:apply-templates select="."/>
61 <xsl:text>\fR</xsl:text>
65 <xsl:template name="inline.monoseq">
66 <xsl:call-template name="code-inline-start"/>
67 <xsl:apply-templates/>
68 <xsl:call-template name="code-inline-end"/>
71 <xsl:template name="code-inline-start">
72 <xsl:if test="not($man.output.better.ps.enabled = 0)">
73 <xsl:text>\FC</xsl:text>
77 <xsl:template name="code-inline-end">
78 <xsl:if test="not($man.output.better.ps.enabled = 0)">
79 <xsl:text>\F[]</xsl:text>
83 <!-- ================================================================== -->
85 <xsl:template name="verbatim-block-start">
86 <xsl:if test="not($man.output.better.ps.enabled = 0)">
87 <xsl:text>.fam C </xsl:text>
88 <xsl:text>.ps -1 </xsl:text>
92 <xsl:template name="verbatim-block-end">
93 <xsl:if test="not($man.output.better.ps.enabled = 0)">
94 <xsl:text>.fam </xsl:text>
95 <xsl:text>.ps +1 </xsl:text>
99 <xsl:template name="synopsis-block-start">
100 <xsl:if test="not($man.output.better.ps.enabled = 0)">
101 <xsl:text>.fam C </xsl:text>
105 <xsl:template name="synopsis-block-end">
106 <xsl:if test="not($man.output.better.ps.enabled = 0)">
107 <xsl:text>.fam </xsl:text>
111 <!-- ================================================================== -->
113 <!-- * NOTE TO DEVELOPERS: For ease of maintenance, the current -->
114 <!-- * manpages stylesheets use the mode="prevent.line.breaking" -->
115 <!-- * templates for anything and everything that needs to have -->
116 <!-- * embedded spaces turned into no-break spaces in output - in -->
117 <!-- * order to prevent that output from getting broken across lines -->
119 <!-- * So if you add anything that whose output, try to apply this -->
120 <!-- * template to it rather than writing separate code to format -->
121 <!-- * it. This can be a little odd if the content you want to -->
122 <!-- * format is not element content; in those cases, you need to -->
123 <!-- * turn it into element content before applying the template; -->
124 <!-- * see examples of this in the existing code. -->
126 <!-- * This template is currently called by the funcdef and paramdef -->
127 <!-- * and group/arg templates. -->
128 <xsl:template mode="prevent.line.breaking" match="*">
129 <xsl:variable name="rcontent">
130 <xsl:apply-templates/>
132 <xsl:variable name="content">
133 <xsl:value-of select="normalize-space($rcontent)"/>
135 <xsl:call-template name="string.subst">
136 <xsl:with-param name="string" select="$content"/>
137 <xsl:with-param name="target" select="' '"/>
138 <!-- * U+2580 is a "UPPER HALF BLOCK"; we use it here because -->
139 <!-- * if we were to just use a normal space, it would get -->
140 <!-- * replaced when normalization is done. We replace it -->
141 <!-- * later with the groff markup for non-breaking space. -->
142 <xsl:with-param name="replacement" select="'▀'"/>
146 <!-- ================================================================== -->
148 <xsl:template name="suppress.hyphenation">
149 <!-- * we need to suppress hyphenation inline only if hyphenation is -->
150 <!-- * actually on, and even then only outside of Cmdsynopsis and -->
151 <!-- * Funcsynopsis, where it is already always turned off -->
152 <xsl:if test="$man.hyphenate != 0 and
153 not(ancestor::cmdsynopsis) and
154 not(ancestor::funcsynopsis)">
155 <xsl:text>\%</xsl:text>
159 <!-- ================================================================== -->
161 <!-- * The replace.dots.and.dashes template is used to cause real -->
162 <!-- * dots and dashes to be output in the top comment (instead of -->
163 <!-- * escaped ones as in the source for the text displayed in the -->
164 <!-- * body of the page) -->
165 <xsl:template name="replace.dots.and.dashes">
166 <xsl:param name="content">
167 <xsl:apply-templates/>
169 <xsl:variable name="dot-content">
170 <xsl:call-template name="string.subst">
171 <xsl:with-param name="string" select="$content"/>
172 <xsl:with-param name="target" select="'\&.'"/>
173 <xsl:with-param name="replacement" select="'.'"/>
176 <xsl:call-template name="string.subst">
177 <xsl:with-param name="string" select="$dot-content"/>
178 <xsl:with-param name="target" select="'\-'"/>
179 <xsl:with-param name="replacement" select="'-'"/>
183 <!-- ================================================================== -->
185 <!-- * The nested-section-title template is called for refsect3, and any -->
186 <!-- * refsection nested more than 2 levels deep. -->
187 <xsl:template name="nested-section-title">
188 <xsl:text>.sp </xsl:text>
189 <xsl:call-template name="pinch.together"/>
190 <xsl:text>.ps +1 </xsl:text>
191 <xsl:call-template name="make.bold.title"/>
194 <xsl:template name="pinch.together">
195 <!-- * arcane roff code to suppress line spacing after headings -->
196 <xsl:text>.it 1 an-trap </xsl:text>
197 <xsl:text>.nr an-no-space-flag 1 </xsl:text>
198 <xsl:text>.nr an-break-flag 1 </xsl:text>
199 <xsl:text>.br </xsl:text>
202 <xsl:template name="make.bold.title">
203 <!-- * make title wrapper so that we can use "bold" template to apply -->
204 <!-- * character formatting to it -->
205 <xsl:variable name="title.wrapper">
207 <xsl:when test="title">
208 <xsl:value-of select="normalize-space(title[1])"/>
211 <xsl:apply-templates select="." mode="object.title.markup.textonly"/>
215 <xsl:call-template name="mark.subheading"/>
216 <xsl:call-template name="bold">
217 <xsl:with-param name="node" select="exsl:node-set($title.wrapper)"/>
218 <xsl:with-param name="context" select="."/>
220 <xsl:text> </xsl:text>
221 <xsl:call-template name="mark.subheading"/>
224 <!-- ================================================================== -->
226 <!-- * The mixed-block template jumps through a few hoops to deal with -->
227 <!-- * mixed-content blocks, so that we don't end up munging verbatim -->
228 <!-- * environments or lists and so that we don't gobble up whitespace -->
229 <!-- * when we shouldn't -->
230 <xsl:template name="mixed-block">
231 <xsl:for-each select="node()">
233 <!-- * Check to see if this node is a verbatim environment. -->
234 <!-- * If so, put a line of space before it. -->
236 <!-- * Yes, address and synopsis are vertabim environments. -->
238 <!-- * The code here previously also treated informaltable as a -->
239 <!-- * verbatim, presumably to support some kludge; I removed it -->
240 <xsl:when test="self::address|self::literallayout|self::programlisting|
241 self::screen|self::synopsis">
242 <xsl:text> </xsl:text>
243 <xsl:text>.sp </xsl:text>
244 <xsl:call-template name="mark.up.block.start"/>
245 <xsl:apply-templates select="."/>
247 <!-- * Check to see if this node is a list; if it is, we don't -->
248 <!-- * want to normalize-space(), so we just apply-templates. -->
249 <!-- * Do same for all admonitions -->
250 <xsl:when test="(self::itemizedlist|self::orderedlist|
251 self::variablelist|self::glosslist|
252 self::simplelist[@type !='inline']|
254 self::caution|self::important|
255 self::note|self::tip|self::warning|
256 self::table|self::informaltable)">
257 <xsl:call-template name="mark.up.block.start"/>
258 <xsl:apply-templates select="."/>
260 <xsl:when test="self::text()">
261 <!-- * Check to see if this is a text node. -->
263 <!-- * If so, replace all whitespace at the beginning or end of it -->
264 <!-- * with a single linebreak. -->
266 <xsl:variable name="content">
267 <xsl:apply-templates select="."/>
270 test="starts-with(translate(.,'	 ',' '), ' ')
271 and preceding-sibling::node()[1][name(.)!='']
272 and normalize-space($content) != ''
274 preceding-sibling::*[1][
280 self::variablelist or
282 self::itemizedlist or
284 self::segmentedlist or
287 self::literallayout or
288 self::programlisting or
295 <xsl:text> </xsl:text>
297 <xsl:value-of select="normalize-space($content)"/>
299 test="(translate(substring(., string-length(.), 1),'	 ',' ') = ' '
300 and following-sibling::node()[1][name(.)!=''])
301 or following-sibling::node()[1][self::comment()]
302 or following-sibling::node()[1][self::processing-instruction()]
304 <xsl:if test="normalize-space($content) != ''
305 or concat(normalize-space($content), ' ') = ' '">
306 <xsl:text> </xsl:text>
311 <!-- * At this point, we know that this node is not a verbatim -->
312 <!-- * environment, list, admonition, or text node; so we can -->
313 <!-- * safely normalize-space() it. -->
314 <xsl:variable name="content">
315 <xsl:apply-templates select="."/>
317 <xsl:value-of select="normalize-space($content)"/>
321 <xsl:call-template name="mark.up.block.end"/>
324 <!-- ================================================================== -->
326 <!-- * Footnote and annotation contents are displayed using a hanging -->
327 <!-- * indent out to $man.indent.width If a paragraph-level block -->
328 <!-- * element (verbatim, list, or admonition) is the first block -->
329 <!-- * element nested at its same level within the same footnote or -->
330 <!-- * annotation, then we push it over by the same indent width. -->
332 <!-- * We don't reset the indent for each following sibling, but -->
333 <!-- * instead do it after for-eaching over all block siblings at -->
334 <!-- * the same level. So the effect is that if there are any -->
335 <!-- * following-sibling blocks after the block that starts this -->
336 <!-- * indent, then they just retain the indent that was already set -->
338 <xsl:template name="mark.up.block.start">
340 <xsl:when test="(ancestor::footnote
341 or ancestor::annotation)">
342 <xsl:if test="not(preceding-sibling::address|
343 preceding-sibling::literallayout|
344 preceding-sibling::programlisting|
345 preceding-sibling::screen|
346 preceding-sibling::synopsis|
347 preceding-sibling::itemizedlist|
348 preceding-sibling::orderedlist|
349 preceding-sibling::variablelist|
350 preceding-sibling::glosslist|
351 preceding-sibling::simplelist[@type !='inline']|
352 preceding-sibling::segmentedlist|
353 preceding-sibling::caution|
354 preceding-sibling::important|
355 preceding-sibling::note|
356 preceding-sibling::tip|
357 preceding-sibling::warning|
358 preceding-sibling::table|
359 preceding-sibling::informaltable
361 <xsl:text>.RS</xsl:text>
362 <xsl:if test="not($list-indent = '')">
363 <xsl:text> </xsl:text>
364 <xsl:value-of select="$list-indent"/>
366 <xsl:text> </xsl:text>
372 <!-- * Check to see if we were called from a block within a footnote or -->
373 <!-- * annotation; if so, and the block contains any nested block -->
374 <!-- * content, then we know the mark.up.block.end template was already -->
375 <!-- * called to generate a .RS macro to indent that nested block -->
376 <!-- * content; so we need to generate a .RE to set the margin back to -->
377 <!-- * where it was prior to the .RS call. -->
378 <xsl:template name="mark.up.block.end">
379 <xsl:if test="(ancestor::footnote
380 or ancestor::annotation)">
381 <xsl:if test="address|
390 simplelist[@type !='inline']|
399 <xsl:text> </xsl:text>
400 <xsl:text>.RE</xsl:text>
401 <xsl:text> </xsl:text>
406 <!-- ================================================================== -->
408 <!-- * The person.name template in the HTML stylesheets outputs extra -->
409 <!-- * spaces that we need to strip out for manpages output. This -->
410 <!-- * template calls person.name, then tries to do some smart -->
411 <!-- * normalization of the result tree fragment from that. -->
412 <xsl:template name="person.name.normalized">
413 <xsl:variable name="contents">
414 <xsl:call-template name="person.name"/>
416 <!-- * We put the output of person.name into a node-set and then we -->
417 <!-- * check it node-by-node and strip out space only where needed. -->
418 <xsl:variable name="contents.tree" select="exsl:node-set($contents)"/>
419 <xsl:for-each select="$contents.tree/node()">
421 <!-- * We don't want to monkey with single spaces or commas/periods -->
422 <!-- * followed by spaces, because those are bits of text that are -->
423 <!-- * actually generated by the person.name template itself (that -->
424 <!-- * is, they're not in the source). So, we preserve them. -->
425 <xsl:when test=". = ' ' or . = ', ' or . = '. '">
426 <xsl:value-of select="."/>
429 <xsl:value-of select="normalize-space(.)"/>
435 <!-- ================================================================== -->
437 <xsl:template name="make.adjusted.man.filename">
438 <xsl:param name="name"/>
439 <xsl:param name="lang"/>
440 <xsl:param name="name.with.lang">
442 <xsl:when test="$lang != 'en'
443 and not($man.output.lang.in.name.enabled = 0)
444 and ($man.output.subdirs.enabled = 0 or
445 $man.output.in.separate.dir = 0)">
446 <!-- * $lang is not en (English) -->
447 <!-- * AND user has specified man.output.lang.in.name.enabled -->
448 <!-- * AND doesn't want output going into separate dirs, -->
449 <!-- * SO... we include the $lang value in the filename; e.g., -->
451 <xsl:value-of select="concat($name, '.', $lang)"/>
454 <!-- * user either has man.output.lang.in.name.enabled unset -->
455 <!-- * or has set it but also has man.output.subdirs.enabled -->
456 <!-- * set (in which case the $lang value is used to add a -->
457 <!-- * $lang subdir in the pathname); in either case, we don't -->
458 <!-- * want to include the $lang in the filename -->
459 <xsl:value-of select="$name"/>
463 <xsl:param name="section"/>
464 <xsl:param name="dirname">
465 <xsl:if test="not($man.output.in.separate.dir = 0)">
467 <xsl:when test="not($man.output.subdirs.enabled = 0)">
468 <xsl:variable name="lang.subdir">
469 <xsl:if test="not($man.output.lang.in.name.enabled = 0)">
470 <!-- * user has man.output.lang.in.name.enabled set, so -->
471 <!-- * we need to add a $lang subdir -->
472 <xsl:value-of select="concat($lang, '/')"/>
476 select="concat($man.output.base.dir, $lang.subdir,
477 'man', normalize-space($section), '/')"/>
480 <xsl:value-of select="$man.output.base.dir"/>
485 <xsl:call-template name="string.subst">
486 <!-- * To create the man filename, replace any spaces in filename with -->
487 <!-- * underscores and then append a dot plus a section number. -->
488 <xsl:with-param name="string"
489 select="concat($dirname,
490 normalize-space($name.with.lang),
491 '.', normalize-space($section))"/>
492 <xsl:with-param name="target" select="' '"/>
493 <xsl:with-param name="replacement" select="'_'"/>
497 <!-- ================================================================== -->
499 <xsl:template name="make.subheading">
500 <xsl:param name="title"/>
501 <xsl:call-template name="mark.subheading"/>
502 <xsl:text>.SH</xsl:text>
503 <xsl:text> </xsl:text>
504 <xsl:text>"</xsl:text>
506 <xsl:when test="not($man.output.better.ps.enabled = 0)">
507 <xsl:value-of select="$title"/>
510 <xsl:call-template name="string.upper">
511 <xsl:with-param name="string" select="$title"/>
515 <xsl:text>"</xsl:text>
516 <xsl:text> </xsl:text>
517 <xsl:call-template name="mark.subheading"/>
520 <!-- * Put a horizontal rule or other divider around section titles -->
521 <!-- * in roff source (just to make things easier to read). -->
522 <xsl:template name="mark.subheading">
523 <xsl:if test="$man.subheading.divider.enabled != 0">
524 <xsl:text>.\" </xsl:text>
525 <xsl:value-of select="$man.subheading.divider"/>
526 <xsl:text> </xsl:text>
530 <!-- ================================================================== -->
532 <xsl:template name="roff-if-else-start">
533 <xsl:param name="condition">n</xsl:param>
534 <xsl:text>.ie </xsl:text>
535 <xsl:value-of select="$condition"/>
536 <xsl:text> \{\ </xsl:text>
539 <xsl:template name="roff-if-start">
540 <xsl:param name="condition">n</xsl:param>
541 <xsl:text>.if </xsl:text>
542 <xsl:value-of select="$condition"/>
543 <xsl:text> \{\ </xsl:text>
546 <xsl:template name="roff-else">
547 <xsl:text>.\} </xsl:text>
548 <xsl:text>.el \{\ </xsl:text>
551 <xsl:template name="roff-if-end">
552 <xsl:text>.\} </xsl:text>