<?xml version="1.0" encoding="us-ascii"?>
<!DOCTYPE stylesheet [
	<!ENTITY show-hidden "false()">
	<!ENTITY visible "&show-hidden; or not(@hidden='yes')">
	<!ENTITY is-not-current "generate-id(current()) != generate-id(.)">
	<!ENTITY value "/dictionary/suite/class | /dictionary/suite/enumeration | /dictionary/suite/record-type | /dictionary/suite/value-type">
]>

<xsl:stylesheet version="1.0"
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:func="http://exslt.org/functions"
	xmlns:sdef="http://apple.com/sdef/functions"
	extension-element-prefixes="func"
	>

	<!--
	<xsl:param name="show-hidden" select="false()"/>
	-->
	<xsl:param name="show-inherited" select="false()"/>

	<!-- Display Parameters -->
	<xsl:param name="show-camel-case" select="false()"/>
	<xsl:param name="quote-enumerations" select="false()"/>
	<xsl:param name="prefix-enumerations" select="false()"/>
	<xsl:param name="colon-ize-parameters" select="false()"/>
	<xsl:param name="colon-ize-direct-parameters" select="false()"/>
	<xsl:param name="str-application-prefix"/>
	<xsl:param name="str-command" select="'v'"/>
	<xsl:param name="str-event" select="'ve'"/>
	<xsl:param name="str-class" select="'n'"/>
	<xsl:param name="str-responds-to" select="'responds to'"/>

	<xsl:output method="html" encoding="utf-8"/>

	<!--
	  Support Functions
	  -->

	<xsl:key name="type" match="&value;" use="@name"/>
	<xsl:key name="type-id" match="&value;" use="@id"/>

	<xsl:key name="class" match="/dictionary/suite/class" use="@name"/>

	<xsl:key name="command" match="/dictionary/suite/command" use="@name"/>
	<xsl:key name="command-id" match="/dictionary/suite/command" use="@id"/>

	<xsl:key name="extends" match="/dictionary/suite/class-extension" use="@extends"/>

	<xsl:key name="xref" match="&value; | dictionary/suite/command" use="@name"/>
	<xsl:key name="xref-id" match="&value; | dictionary/suite/command" use="@id"/>

	<xsl:key name="element-of-all" match="/dictionary/suite/class | /dictionary/suite/class-extension" use="element/@type"/>
	<xsl:key name="element-of-visible" match="/dictionary/suite/class | /dictionary/suite/class-extension" use="element[not(@hidden='yes')]/@type"/>
		<!-- need to use two keys because we can't use params in a "use" expresion. -->

	<func:function name="sdef:idfys">
		<xsl:param name="p"/>
		<xsl:variable name="nonid" select="translate($p, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_', '')"/>
		<func:result select="translate($p, $nonid, '--------------------------------')"/>
	</func:function>

	<func:function name="sdef:id">
		<xsl:param name="p"/>
		<xsl:variable name="name" select="($p/@name | $p/@extends | $p/@title)[1]"/>
		<xsl:choose>
			<xsl:when test="$p/@id">
				<func:result select="$p/@id"/>
			</xsl:when>
			<xsl:when test="$name">
				<func:result>
					<xsl:if test="local-name($p) != 'suite'">
						<xsl:value-of select="sdef:id($p/..)"/>
						<xsl:text>.</xsl:text>
					</xsl:if>
					<xsl:value-of select="sdef:idfys($name)"/>
				</func:result>
			</xsl:when>
			<xsl:otherwise>
				<xsl:message>
					<xsl:text>Called sdef:id on a </xsl:text>
					<xsl:value-of select="local-name($p)"/>
					<xsl:text> node that has no name or id!</xsl:text>
				</xsl:message>
				<func:result select="sdef:idfys(string($p))"/>
			</xsl:otherwise>
		</xsl:choose>
	</func:function>

	<xsl:template name="apply-hidden">
		<xsl:param name="hidden" select="@hidden = 'yes'"/>
		<xsl:if test="$hidden">
			<xsl:attribute name="hidden">yes</xsl:attribute>
		</xsl:if>
	</xsl:template>


	<!-- Translating Case -->

	<xsl:variable name="sdef:lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
	<xsl:variable name="sdef:upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
	
	<func:function name="sdef:upper-case">
		<xsl:param name="text"/>
		<func:result select="translate($text, $sdef:lower, $sdef:upper)"/>
	</func:function>

	<func:function name="sdef:lower-case">
		<xsl:param name="text"/>
		<func:result select="translate($text, $sdef:upper, $sdef:lower)"/>
	</func:function>


	<!-- Transform Names to Camel-Case, Etc. -->

	<xsl:template name="transform-tail">
		<xsl:param name="text"/>
		<xsl:if test="$text">
			<xsl:choose>
				<xsl:when test="$show-camel-case">
					<xsl:value-of select="sdef:upper-case(substring($text,1,1))"/>
					<xsl:value-of select="substring-before(concat(substring($text,2), ' '), ' ')"/>
					<xsl:call-template name="transform-tail">
						<xsl:with-param name="text" select="substring-after(substring($text,2), ' ')"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="$text"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:if>
	</xsl:template>

	<xsl:template name="transform-class">
		<xsl:param name="text"/>
		<xsl:if test="$text">
			<xsl:value-of select="$str-application-prefix"/>
			<xsl:call-template name="transform-tail">
				<xsl:with-param name="text" select="$text"/>
			</xsl:call-template>
		</xsl:if>
	</xsl:template>

	<xsl:template name="transform-name">
		<xsl:param name="text"/>
		<xsl:if test="$text">
			<xsl:choose>
				<xsl:when test="$show-camel-case">
					<xsl:value-of select="sdef:lower-case(substring-before(concat($text, ' '), ' '))"/>
					<xsl:call-template name="transform-tail">
						<xsl:with-param name="text" select="substring-after(substring($text,2), ' ')"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="$text"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:if>
	</xsl:template>

	<xsl:template name="transform-enum-group">
		<xsl:param name="enumeration-name"/>
		<xsl:if test="$enumeration-name">
			<xsl:value-of select="$str-application-prefix"/>
			<xsl:choose>
				<xsl:when test="$prefix-enumerations">
					<xsl:call-template name="transform-tail">
						<xsl:with-param name="text" select="$enumeration-name"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:otherwise>
					<xsl:value-of select="$enumeration-name"/>
				</xsl:otherwise>
			</xsl:choose>
		</xsl:if>
	</xsl:template>

	<xsl:template name="transform-enum">
		<xsl:param name="enumeration-name"/>
		<xsl:param name="text"/>
		<xsl:if test="$text">
			<xsl:variable name="transformedText">
				<xsl:choose>
					<xsl:when test="$prefix-enumerations">
						<xsl:call-template name="transform-tail">
							<xsl:with-param name="text" select="concat($enumeration-name, ' ', $text)"/>
						</xsl:call-template>
					</xsl:when>
					<xsl:otherwise>
						<xsl:value-of select="$text"/>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:variable>
			<xsl:if test="$quote-enumerations"><xsl:text>"</xsl:text></xsl:if>
			<xsl:value-of select="$str-application-prefix"/>
			<xsl:value-of select="$transformedText"/>
			<xsl:if test="$quote-enumerations"><xsl:text>"</xsl:text></xsl:if>
		</xsl:if>
	</xsl:template>


	<xsl:template name="plural">
		<xsl:param name="node"/>

		<xsl:choose>
			<xsl:when test="$node/@root='yes' or $node/@name='application'">
				<xsl:value-of select="$node/@name"/>
			</xsl:when>
			<xsl:when test="$node/@plural"><xsl:value-of select="$node/@plural"/></xsl:when>
			<xsl:otherwise><xsl:value-of select="concat($node/@name, 's')"/></xsl:otherwise>
		</xsl:choose>
	</xsl:template>

	<xsl:template name="inline-enum">
		<xsl:param name="node"/>
		<xsl:param name="length" select="99999"/>
		<xsl:param name="link-all"/>
		<xsl:for-each select="$node/enumerator[&visible;]">
			<xsl:choose>
				<xsl:when test="position() &lt;= number($length)">
					<xsl:if test="@hidden = 'yes'">
						<xsl:text disable-output-escaping="yes">&lt;span hidden="yes"&gt;</xsl:text>
					</xsl:if>
					<xsl:call-template name="transform-enum">
						<xsl:with-param name="enumeration-name" select="$node/@name"/>
						<xsl:with-param name="text" select="@name"/>
					</xsl:call-template>
					<xsl:if test="position() != last()">
						<xsl:text>/&#8204;</xsl:text>
					</xsl:if>
					<xsl:if test="@hidden = 'yes'">
						<xsl:text disable-output-escaping="yes">&lt;/span&gt;</xsl:text>
					</xsl:if>
				</xsl:when>
				<xsl:when test="position() = $length + 1">
					<xsl:choose>
						<xsl:when test="$link-all">
							<i><xsl:text disable-output-escaping="yes">more&amp;hellip;</xsl:text></i>
						</xsl:when>
						<xsl:otherwise>
							<a>
								<xsl:attribute name="href">
									<xsl:text>#</xsl:text>
									<xsl:value-of select="sdef:id($node)"/>
								</xsl:attribute>
								<i><xsl:text disable-output-escaping="yes">more&amp;hellip;</xsl:text></i>
							</a>
						</xsl:otherwise>
					</xsl:choose>
				</xsl:when>
			</xsl:choose>
		</xsl:for-each>
	</xsl:template>

	<xsl:template name="type-link">
		<xsl:param name="name"/>
		<xsl:param name="plural"/>
		<xsl:param name="recurse"/>
		<xsl:param name="isElement" select="false()"/>

		<xsl:variable name="node" select="(key('type-id', $name) | key('type', $name))[1]"/>

		<xsl:choose>
			<xsl:when test="name($node) = 'class' or name($node) = 'record-type' or name($node) = 'value-type'">
				<a>
					<xsl:attribute name="href">
						<xsl:text>#</xsl:text>
						<xsl:value-of select="sdef:id($node)"/>
					</xsl:attribute>
					<xsl:variable name="nameToCamelCase">
						<xsl:choose>
							<xsl:when test="$plural">
								<xsl:call-template name="plural">
									<xsl:with-param name="node" select="$node"/>
								</xsl:call-template>
							</xsl:when>
							<xsl:otherwise><xsl:value-of select="$node/@name"/></xsl:otherwise>
						</xsl:choose>
					</xsl:variable>
					<xsl:choose>
						<xsl:when test="$isElement">
							<xsl:call-template name="transform-name">
								<xsl:with-param name="text" select="$nameToCamelCase"/>
							</xsl:call-template>
						</xsl:when>
						<xsl:otherwise>
							<xsl:call-template name="transform-class">
								<xsl:with-param name="text" select="$nameToCamelCase"/>
							</xsl:call-template>
						</xsl:otherwise>
					</xsl:choose>
				</a>
				<xsl:if test="$recurse and $node/@inherits and not($node/@inherits = $node/@name)">
					<xsl:text> &gt; </xsl:text>
					<xsl:choose>
						<xsl:when test="$recurse = 1">
							<xsl:text disable-output-escaping="yes">&amp;hellip;</xsl:text>
						</xsl:when>
						<xsl:otherwise>
							<xsl:call-template name="type-link">
								<xsl:with-param name="name" select="$node/@inherits"/>
								<xsl:with-param name="plural" select="$plural"/>
								<xsl:with-param name="recurse" select="$recurse - 1"/>
								<xsl:with-param name="isElement" select="$isElement"/>
							</xsl:call-template>
						</xsl:otherwise>
					</xsl:choose>
				</xsl:if>
			</xsl:when>
			<xsl:when test="name($node) = 'enumeration'">
				<xsl:variable name="length">
					<xsl:choose>
						<xsl:when test="$node/@inline"><xsl:value-of select="number($node/@inline)"/></xsl:when>
						<xsl:otherwise><xsl:value-of select="99999"/></xsl:otherwise>
					</xsl:choose>
				</xsl:variable>
				<xsl:variable name="link-enumeration-name" select="$node[&visible;] and ($length = 0 or $prefix-enumerations)"/>
				<xsl:variable name="link-all" select="$link-enumeration-name or ($node[sdef:show-enumeration()] and (count($node/enumerator[&visible;]) &lt;= $length))"/>
				<xsl:choose>
					<xsl:when test="$link-all">
						<a>
							<xsl:attribute name="href">
								<xsl:text>#</xsl:text>
								<xsl:value-of select="sdef:id($node)"/>
							</xsl:attribute>
							<xsl:choose>
								<xsl:when test="$link-enumeration-name">
									<xsl:call-template name="transform-enum-group">
										<xsl:with-param name="enumeration-name" select="$node/@name"/>
									</xsl:call-template>
								</xsl:when>
								<xsl:otherwise>
									<xsl:call-template name="inline-enum">
										<xsl:with-param name="node" select="$node"/>
										<xsl:with-param name="length" select="$length"/>
										<xsl:with-param name="link-all" select="$link-all"/>
									</xsl:call-template>
								</xsl:otherwise>
							</xsl:choose>
						</a>
					</xsl:when>
					<xsl:when test="not($node/@inline)">
						<xsl:call-template name="inline-enum">
							<xsl:with-param name="node" select="$node"/>
						</xsl:call-template>
					</xsl:when>
					<xsl:otherwise>
						<xsl:call-template name="inline-enum">
							<xsl:with-param name="node" select="$node"/>
							<xsl:with-param name="length" select="$node/@inline"/>
						</xsl:call-template>
					</xsl:otherwise>
				</xsl:choose>
			</xsl:when>
			<xsl:otherwise>
				<xsl:value-of select="$name"/>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>

	<xsl:template name="type-node">
		<xsl:choose>
			<xsl:when test="@type">
				<xsl:call-template name="type-link">
					<xsl:with-param name="name" select="@type"/>
				</xsl:call-template>
			</xsl:when>
			<xsl:when test="./type[&visible;]">
				<xsl:for-each select="./type[&visible;]">
					<xsl:if test="@list = 'yes'"><xsl:text>list of </xsl:text></xsl:if>
					<xsl:call-template name="type-node"/>
					<xsl:if test="position() != last()">
						<xsl:if test="last() &gt; 2"><xsl:text>,</xsl:text></xsl:if>
						<xsl:text> </xsl:text>
						<xsl:if test="position() = last()-1"><xsl:text>or </xsl:text></xsl:if>
					</xsl:if>
				</xsl:for-each>
			</xsl:when>
			<xsl:otherwise>
				<i><xsl:text>undefined</xsl:text></i>
			</xsl:otherwise>
		</xsl:choose>
	</xsl:template>


	<!--
	  DEFAULT RULES
	  -->

	<xsl:template match="*">
		<!-- don't process children recursively unless a template says so. -->
	</xsl:template>

	<xsl:template match="*[not(&visible;)]">
		<!-- don't process children of hidden elements. -->
	</xsl:template>

	<xsl:template match="/">
		<!-- start things rolling. -->
		<xsl:apply-templates/>
	</xsl:template>


	<!--
	  DOCUMENTATION
	  -->

	<xsl:template match="dictionary/documentation">
		<div class="entry">
			<xsl:apply-templates/>
		</div>
	</xsl:template>

	<xsl:template match="suite/documentation">
		<div class="entry">
			<xsl:apply-templates/>
		</div>
	</xsl:template>

	<xsl:template match="documentation">
		<xsl:apply-templates/>
	</xsl:template>

	<xsl:template match="documentation/html">
		<div class="documentation">
			<xsl:apply-templates mode="html"/>
		</div>
	</xsl:template>

	<xsl:template mode="html" match="*">
		<xsl:copy-of select="."/>
	</xsl:template>

	<xsl:template mode="html" match="text()">
		<xsl:value-of disable-output-escaping="yes" select="."/>
	</xsl:template>


	<!--
	  DICTIONARY and SUITES
	  -->

	<xsl:template match="/dictionary">
		<html>
		<head>
			<link rel="stylesheet" type="text/css" href="apple-bundle-resource://com.apple.OSAKit/dictionary.css"/>
			<title><xsl:value-of select="@name"/></title>
		</head>
		<body>
			<xsl:apply-templates/>
		</body>
		</html>
	</xsl:template>

	<xsl:template match="suite[&visible;]">
		<div class="suite">
		<xsl:attribute name="id">
			<xsl:value-of select="sdef:id(.)"/>
		</xsl:attribute>
		<xsl:call-template name="apply-hidden"/>
		<table class="suite">
			<tr>
				<td><xsl:value-of select="(@title | @name)[1]"/></td>
					<!-- be nice for now to old sdefs. -->
				<td><xsl:value-of select="@description"/></td>
			</tr>
		</table>
		<xsl:apply-templates/>
		</div>
	</xsl:template>


	<!--
	  CLASSES
	  -->

	<!-- A complete class definition consists of the current element (either a <class> or a <class-extension>) plus zero or more "fragments": any other <class>es/<class-extension>s with the same name/extends.  (Properly formed sdefs will only have one <class> with a given name, but older ones may have several.)  We distinguish between *internal* fragments, which are in the same suite as the current element, and *external* ones, which are in other suites.  Internal fragments are combined with the current element into a single entry with divisions.  External fragments are linked via cross-reference, and *may* also be combined if "Show inherited items" is on. -->

	<xsl:template match="class[&visible;] | record-type[&visible;] | value-type[&visible;]">
		<xsl:call-template name="class-body">
			<xsl:with-param name="name" select="@name"/>
		</xsl:call-template>
	</xsl:template>
	
	<xsl:template match="class-extension[&visible;]">
		<xsl:variable name="all-fragments" select="(key('class', @extends) | key('extends', @extends) | key('extends', @id))[&visible;]"/>
		<xsl:variable name="first-fragment-in-this-suite" select="($all-fragments[generate-id(current()/..) = generate-id(..)])[1]"/>
		<xsl:if test="generate-id(.) = generate-id($first-fragment-in-this-suite)">
			<!-- only generate output if this class-extension is an external fragment; otherwise, it will be handled in its base class. -->
			<xsl:variable name="extends-class" select="(key('type-id', @extends) | key('type', @extends))[1]"/>
			<xsl:variable name="extends-name" select="$extends-class/@name | @extends"/>
			<xsl:call-template name="class-body">
				<xsl:with-param name="name" select="$extends-name"/>
			</xsl:call-template>
		</xsl:if>
	</xsl:template>
	
	<xsl:template name="class-body">
		<xsl:param name="name"/>

		<xsl:variable name="other-fragments" select="(key('class', $name) | key('extends', $name) | key('extends', @id))[&visible; and &is-not-current;]"/>
		<xsl:variable name="internal-fragments" select="$other-fragments[generate-id(current()/..) = generate-id(..)]"/>
		<xsl:variable name="external-fragments" select="$other-fragments[generate-id(current()/..) != generate-id(..)]"/>

		<div class="entry">
			<xsl:attribute name="id">
				<xsl:value-of select="sdef:id(.)"/>
			</xsl:attribute>
			<xsl:call-template name="apply-hidden"/>
			<p class="entry">
				<!-- name and plural. -->
				<span class="name">
					<xsl:call-template name="transform-class">
						<xsl:with-param name="text" select="$name"/>
					</xsl:call-template>
				</span>
				<xsl:text disable-output-escaping="yes">&amp;ensp;</xsl:text>
				<span class="annot"><xsl:value-of select="$str-class"/></span>
				<xsl:if test="@plural and @plural != concat($name, 's')">
					<span class="annot">, pl </span>
					<span class="name">
						<xsl:call-template name="transform-name">
							<xsl:with-param name="text" select="@plural"/>
						</xsl:call-template>
					</span>
				</xsl:if>

				<!-- cross-references to inherited classes and external fragments (if any). -->
				<xsl:if test="@inherits or count($external-fragments) > 0">
					<xsl:text> [</xsl:text>
					<xsl:if test="@inherits">
						<xsl:text>inh. </xsl:text>
						<xsl:call-template name="type-link">
							<xsl:with-param name="name" select="@inherits"/>
							<xsl:with-param name="recurse" select="5"/>
						</xsl:call-template>
					</xsl:if>
					<xsl:if test="count($external-fragments) > 0">
						<xsl:if test="@inherits">
							<xsl:text>; </xsl:text>
						</xsl:if>
						<xsl:text>see also </xsl:text>
					</xsl:if>
					<xsl:for-each select="$external-fragments">
						<a>
							<xsl:call-template name="apply-hidden"/>
							<xsl:attribute name="href">
								<xsl:text>#</xsl:text>
								<xsl:value-of select="sdef:id(.)"/>
							</xsl:attribute>
							<xsl:value-of select="(../@title | ../@name)[1]"/>
						</a>
						<xsl:if test="position() != last()">
							<xsl:text>, </xsl:text>
						</xsl:if>
					</xsl:for-each>
					<xsl:text>]</xsl:text>
				</xsl:if>

				<!-- description. -->
				<xsl:if test="@description">
					<xsl:text> : </xsl:text>
					<span class="description"><xsl:value-of select="@description"/></span>
				</xsl:if>

				<!-- synonyms. -->
				<xsl:call-template name="synonyms"/>
			</p>
			<!-- current element contents... -->
			<xsl:call-template name="class-guts"/>
			<!-- ...and any internal fragments. -->
			<xsl:for-each select="$internal-fragments">
				<div class="fragment">
					<p class="label">
						<span class="title">
							<xsl:value-of select="@title"/>
							<xsl:if test="not(@title)">
								<xsl:value-of select="@description"/>
							</xsl:if>
						</span>
						<xsl:if test="@title and @description">
							<xsl:text disable-output-escaping="yes">&amp;nbsp;&amp;mdash; </xsl:text>
							<xsl:value-of select="@description"/>
						</xsl:if>
					</p>
					<xsl:call-template name="class-guts"/>
				</div>
			</xsl:for-each>
			<!-- if "show inherited items" is on... -->
			<xsl:if test="$show-inherited">
				<!-- ...also show external fragments... -->
				<xsl:for-each select="$external-fragments">
					<div class="fragment">
						<p class="label">
							<xsl:value-of select="@description"/>
							<xsl:text> [see </xsl:text>
							<xsl:value-of select="../@name"/>
							<xsl:text>]</xsl:text>
						</p>
						<xsl:call-template name="class-guts"/>
					</div>
				</xsl:for-each>
				<!-- ...and the contents of the inherited class. -->
				<xsl:if test="@inherits and @inherits != $name">
					<xsl:for-each select="(key('class', @inherits)[&is-not-current;])[1]">
						<div class="fragment">
							<!-- using "for-each" with one element this way sets the current element. -->
							<p class="label">
								<xsl:text>inherited from </xsl:text>
								<xsl:value-of select="@name"/>
							</p>
							<xsl:call-template name="class-guts"/>
						</div>
					</xsl:for-each>
				</xsl:if>
			</xsl:if>
		</div>
	</xsl:template>

	<xsl:template name="class-guts">
		<xsl:variable name="first-p" select="(contents | property)[1]"/>
		<xsl:variable name="last-p" select="(contents | property)[last()]"/>
		<xsl:variable name="between-p" select="$first-p/following-sibling::*[name() = 'contents' or name() = 'property' or name() = 'documentation'][count(. | $last-p/preceding-sibling::*[name() = 'contents' or name() = 'property' or name() = 'documentation']) = count($last-p/preceding-sibling::*[name() = 'contents' or name() = 'property' or name() = 'documentation'])]"/>
			<!-- The intersection of two node-sets $ns1 and $ns2 is "$ns1[count(. | $ns2)=count($ns2)]" (the Kayessian method). -->

		<xsl:if test="$first-p">
			<xsl:apply-templates select="$first-p/preceding-sibling::documentation"/>
		</xsl:if>
		<xsl:if test="not($first-p)">
			<xsl:apply-templates select="documentation"/>
		</xsl:if>

		<xsl:call-template name="elements"/>

		<xsl:variable name="properties" select="($first-p | $between-p | $last-p)[&visible;]"/>
		<xsl:if test="$properties">
			<p class="label">Properties</p>
			<xsl:apply-templates select="$properties"/>
		</xsl:if>

		<xsl:variable name="responds-to" select="responds-to[&visible;]"/>
		<xsl:if test="$responds-to">
			<p class="label"><xsl:value-of select="$str-responds-to"/></p>
			<xsl:apply-templates select="$responds-to"/>
		</xsl:if>

		<xsl:if test="$last-p">
			<xsl:apply-templates select="$last-p/following-sibling::documentation"/>
		</xsl:if>

		<xsl:variable name="xref" select="xref[&visible;]"/>
		<xsl:if test="$xref">
			<p class="label">See Also</p>
			<p><xsl:apply-templates select="$xref"/></p>
		</xsl:if>
	</xsl:template>

	<xsl:template name="elements">
		<xsl:param name="name" select="@name"/>

		<xsl:variable name="parent-contains" select="key('class', @inherits)[&is-not-current;]/element[&show-hidden; or not(@hidden='yes' or key('type', @type)/@hidden='yes')]"/>
		<xsl:variable name="this-contains" select="element[&show-hidden; or not(@hidden='yes' or key('type', @type)/@hidden='yes')]"/>
		<xsl:variable name="contains" select="$this-contains[not(@type=$parent-contains/@type)]"/>

		<xsl:variable name="K">
			<!-- need to use two keys because we can't use params in a "use" expresion. -->
			<xsl:choose>
				<xsl:when test="&show-hidden;"><xsl:text>element-of-all</xsl:text></xsl:when>
				<xsl:otherwise><xsl:text>element-of-visible</xsl:text></xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<xsl:variable name="parent-contained-by" select="key($K, @inherits)[&visible;]"/>
		<xsl:variable name="this-contained-by" select="key($K, $name)[&visible;]"/>
		<xsl:variable name="contained-by" select="$this-contained-by[not(@name=$parent-contained-by/@name)]"/>

		<!-- elements of this class. -->
		<xsl:if test="$contains or $contained-by">
			<p class="label">Elements</p>
			<p>
				<xsl:if test="$contains">
					<xsl:text>contains </xsl:text>
					<xsl:for-each select="$contains">
						<xsl:call-template name="element-list-item">
							<xsl:with-param name="type" select="@type"/>
							<xsl:with-param name="hidden" select="@hidden='yes' or key('type', @type)/@hidden='yes'"/>
						</xsl:call-template>
					</xsl:for-each>
				</xsl:if>
				<xsl:if test="$contained-by">
					<xsl:if test="$contains">
						<xsl:text>; </xsl:text>
					</xsl:if>
					<xsl:text>contained by </xsl:text>
					<xsl:for-each select="$contained-by">
						<xsl:call-template name="element-list-item">
							<xsl:with-param name="type" select="@name | @extends"/>
							<xsl:with-param name="hidden" select="@hidden='yes' or ./element[@type=$name]/@hidden='yes'"/>
						</xsl:call-template>
					</xsl:for-each>
				</xsl:if>
				<xsl:text>.</xsl:text>
			</p>
		</xsl:if>
	</xsl:template>

	<xsl:template name="element-list-item">
		<xsl:param name="hidden"/>
		<xsl:param name="type"/>
		<span>
			<xsl:call-template name="apply-hidden">
				<xsl:with-param name="hidden" select="$hidden"/>
			</xsl:call-template>
			<xsl:call-template name="type-link">
				<xsl:with-param name="name" select="$type"/>
				<xsl:with-param name="plural" select="true()"/>
				<xsl:with-param name="isElement" select="true()"/>
			</xsl:call-template>
		</span>
		<xsl:if test="position() != last()">
			<xsl:text>, </xsl:text>
		</xsl:if>
	</xsl:template>

	<xsl:template match="contents | property">
		<xsl:variable name="name">
			<xsl:choose>
				<xsl:when test="@name">
					<xsl:call-template name="transform-name">
						<xsl:with-param name="text" select="@name"/>
					</xsl:call-template>
				</xsl:when>
				<xsl:otherwise><xsl:text>contents</xsl:text></xsl:otherwise>
			</xsl:choose>
		</xsl:variable>
		<div class="entry">
			<xsl:attribute name="id">
				<xsl:value-of select="sdef:id(.)"/>
			</xsl:attribute>
			<p class="entry">
				<xsl:call-template name="apply-hidden"/>
				<span class="name">
					<xsl:call-template name="transform-name">
						<xsl:with-param name="text" select="@name"/>
					</xsl:call-template>
				</span>
				<xsl:text> </xsl:text>
				<span class="type">
					<xsl:text>(</xsl:text>
					<xsl:call-template name="type-node"/>
					<xsl:choose>
						<xsl:when test="@access='r'"><xsl:text>, r/o</xsl:text></xsl:when>
						<xsl:when test="@access='w'"><xsl:text>, w/o</xsl:text></xsl:when>
					</xsl:choose>
					<xsl:text>)</xsl:text>
				</span>
				<xsl:if test="@description">
					<xsl:text> : </xsl:text>
					<span class="description"><xsl:value-of select="@description"/></span>
				</xsl:if>
				<xsl:call-template name="synonyms"/>
			</p>
			<xsl:apply-templates/>
		</div>
	</xsl:template>

	<xsl:template match="responds-to">
		<xsl:variable name="node" select="(key('command-id', @command) | key('command', @command) | key('command', @name))[1]"/>
			<!-- should only be one match, but just in case, get only the first. -->
		<xsl:call-template name="reference-list-item">
			<xsl:with-param name="name" select="@command"/>
			<xsl:with-param name="target" select="$node"/>
		</xsl:call-template>
		<xsl:if test="position() != last()"><xsl:text>, </xsl:text></xsl:if>
		<xsl:if test="position() = last()">
			<xsl:text>.</xsl:text>
		</xsl:if>
	</xsl:template>

	<xsl:template match="xref">
		<xsl:variable name="node" select="(key('xref-id', @target) | key('xref', @target))[1]"/>
			<!-- should only be one match, but just in case, get only the first. -->
		<xsl:call-template name="reference-list-item">
			<xsl:with-param name="name" select="@target"/>
			<xsl:with-param name="target" select="$node"/>
		</xsl:call-template>
		<xsl:if test="position() != last()"><xsl:text>, </xsl:text></xsl:if>
		<xsl:if test="position() = last()">
			<xsl:text>.</xsl:text>
		</xsl:if>
	</xsl:template>

	<xsl:template name="reference-list-item">
		<xsl:param name="name"/>
		<xsl:param name="target"/>
		<a>
			<xsl:call-template name="apply-hidden"/>
			<xsl:if test="$target">
				<xsl:attribute name="href">
					<xsl:text>#</xsl:text>
					<xsl:value-of select="sdef:id($target)"/>
				</xsl:attribute>
			</xsl:if>
			<xsl:call-template name="transform-name">
				<xsl:with-param name="text" select="$target/@name"/>
			</xsl:call-template>
			<xsl:if test="not($target)">
				<xsl:call-template name="transform-name">
					<xsl:with-param name="text" select="$name"/>
				</xsl:call-template>
			</xsl:if>
		</a>
	</xsl:template>


	<!--
	  ENUMERATIONS
	  -->
	
	<func:function name="sdef:show-enumeration">
		<!-- Should we show the current enumeration node? -->
		<func:result select="(&visible;) and ($prefix-enumerations or @inline or (not(@name = @code) and (.//*[@description and (&visible;)] or .//documentation[&visible;])))"/>
	</func:function>

	<xsl:template match="enumeration[sdef:show-enumeration()]">
		<div class="entry">
		<xsl:attribute name="id">
			<xsl:value-of select="sdef:id(.)"/>
		</xsl:attribute>
		<xsl:call-template name="apply-hidden"/>
		<p class="entry">
			<span class="name">
				<xsl:call-template name="transform-enum-group">
					<xsl:with-param name="enumeration-name" select="@name"/>
				</xsl:call-template>
			</span>
			<xsl:text disable-output-escaping="yes">&amp;ensp;</xsl:text>
			<span class="annot">enum</span>
			<xsl:if test="@description">
				<xsl:text> : </xsl:text>
				<span class="description"><xsl:value-of select="@description"/></span>
			</xsl:if>
			<xsl:call-template name="synonyms"/>
		</p>
		<xsl:apply-templates/>
		</div>
	</xsl:template>

	<xsl:template match="enumeration[sdef:show-enumeration()]/enumerator">
		<div class="entry">
		<p class="entry">
			<xsl:call-template name="apply-hidden"/>
			<span class="name">
				<xsl:call-template name="transform-enum">
					<xsl:with-param name="enumeration-name" select="../@name"/>
					<xsl:with-param name="text" select="@name"/>
				</xsl:call-template>
			</span>
			<xsl:if test="@description">
				<xsl:text> : </xsl:text>
				<span class="description"><xsl:value-of select="@description"/></span>
			</xsl:if>
			<xsl:call-template name="synonyms"/>
		</p>
		<xsl:apply-templates/>
		</div>
	</xsl:template>


	<!--
	  COMMANDS and EVENTS
	  -->

	<xsl:template match="command[&visible;] | event[&visible;]">
		<div class="entry">
		<xsl:attribute name="id">
			<xsl:value-of select="sdef:id(.)"/>
		</xsl:attribute>
		<xsl:call-template name="apply-hidden"/>
		<p class="entry">
			<span class="name">
				<xsl:call-template name="transform-name">
					<xsl:with-param name="text" select="@name"/>
				</xsl:call-template>
			</span>
			<xsl:text disable-output-escaping="yes">&amp;ensp;</xsl:text>
			<span class="annot">
				<xsl:choose>
					<xsl:when test="name() = 'event'"><xsl:value-of select="$str-event"/></xsl:when>
					<xsl:otherwise><xsl:value-of select="$str-command"/></xsl:otherwise>
				</xsl:choose>
			</span>
			<xsl:if test="@description">
				<xsl:text> : </xsl:text>
				<span class="description"><xsl:value-of select="@description"/></span>
			</xsl:if>
			<xsl:call-template name="synonyms"/>
		</p>
		<xsl:variable name="first-p" select="(direct-parameter | parameter | result)[1]"/>
		<xsl:variable name="last-p" select="(direct-parameter | parameter | result)[last()]"/>
		<xsl:variable name="between-p" select="$first-p/following-sibling::*[count(. | $last-p/preceding-sibling::*) = count($last-p/preceding-sibling::*)]"/>

		<xsl:apply-templates select="$first-p/preceding-sibling::documentation"/>
		<div class="entry verb-summary">
			<xsl:variable name="merge-first-parameter" select="$colon-ize-direct-parameters and not(direct-parameter) and parameter"/>
			<p class="entry">
				<span class="name">
					<xsl:call-template name="transform-name">
						<xsl:with-param name="text">
							<xsl:choose>
								<xsl:when test="$merge-first-parameter">
									<xsl:value-of select="concat(@name, ' ', parameter[1]/@name)"/>
								</xsl:when>
								<xsl:otherwise>
									<xsl:value-of select="@name"/>
								</xsl:otherwise>
							</xsl:choose>
						</xsl:with-param>
					</xsl:call-template>
					<xsl:if test="$merge-first-parameter or ($colon-ize-direct-parameters and direct-parameter)">:</xsl:if>
				</span>
				<xsl:text> </xsl:text>
				<xsl:choose>
					<xsl:when test="$merge-first-parameter">
						<xsl:apply-templates select="parameter[1]" mode="first-parameter"/>
					</xsl:when>
					<xsl:otherwise>
						<xsl:apply-templates select="direct-parameter"/>
					</xsl:otherwise>
				</xsl:choose>
			</p>
			<xsl:apply-templates select="($first-p | $between-p | $last-p)[name() = 'parameter' or name() = 'documentation'][&visible;][not($merge-first-parameter and name() = 'parameter' and count(./preceding-sibling::parameter) = 0)]"/>
			<xsl:apply-templates select="result"/>
		</div>
		<xsl:apply-templates select="$last-p/following-sibling::documentation"/>

		<!-- a command will typically have at least one (direct) parameter or a result, in which case everything is covered by the above. However, if not,  $first-p and $last-p will both be empty, which means they have no siblings and no documentation elements will be processed; so handle them here. -->
		<xsl:if test="not($first-p)">
			<xsl:apply-templates select="child::documentation"/>
		</xsl:if>

		<xsl:variable name="xref" select="xref[&visible;]"/>
		<xsl:if test="$xref">
			<p class="label">See Also</p>
			<p><xsl:apply-templates select="$xref"/></p>
		</xsl:if>
		</div>
	</xsl:template>

	<xsl:template name="basic-parameter">
		<xsl:param name="show-name" select="true()"/>

		<xsl:if test="not($colon-ize-direct-parameters) and @optional = 'yes'">
			<xsl:text>[</xsl:text>
		</xsl:if>
		<xsl:if test="@name and $show-name">
			<span class="name">
				<xsl:call-template name="transform-name">
					<xsl:with-param name="text" select="@name"/>
				</xsl:call-template>
				<xsl:if test="$colon-ize-parameters">:</xsl:if>
			</span>
			<xsl:text> </xsl:text>
		</xsl:if>
		<xsl:if test="$colon-ize-direct-parameters and @optional = 'yes'">
			<xsl:text>[</xsl:text>
		</xsl:if>
		<xsl:call-template name="type-node"/>
		<xsl:if test="@optional = 'yes'">
			<xsl:text>]</xsl:text>
		</xsl:if>
		<xsl:if test="@description">
			<xsl:text> : </xsl:text>
			<span class="description"><xsl:value-of select="@description"/></span>
		</xsl:if>
		<xsl:call-template name="synonyms"/>
	</xsl:template>

	<xsl:template match="direct-parameter[&visible;]">
		<span>
			<xsl:call-template name="apply-hidden"/>
			<xsl:call-template name="basic-parameter"/>
		</span>
	</xsl:template>

	<xsl:template match="parameter[&visible;]" mode="first-parameter">
		<span>
			<xsl:call-template name="apply-hidden"/>
			<xsl:call-template name="basic-parameter">
				<xsl:with-param name="show-name" select="false()"/>
			</xsl:call-template>
		</span>
	</xsl:template>

	<xsl:template match="parameter[&visible;]">
		<div class="entry">
			<p class="entry">
				<xsl:call-template name="apply-hidden"/>
				<xsl:call-template name="basic-parameter"/>
			</p>
			<xsl:apply-templates/>
		</div>
	</xsl:template>

	<xsl:template match="result">
		<div class="entry">
			<p class="entry">
				<xsl:text disable-output-escaping="yes">&amp;rarr; </xsl:text>
				<xsl:call-template name="type-node"/>
				<xsl:if test="@description">
					<xsl:text> : </xsl:text>
					<span class="description"><xsl:value-of select="@description"/></span>
				</xsl:if>
			</p>
			<xsl:apply-templates/>
		</div>
	</xsl:template>

	<!--
	  SYNONYMS
	  -->

	<xsl:template name="synonyms">
		<xsl:variable name="syn" select="./synonym[@name and (&visible;)]"/>
		<xsl:variable name="isClass" select="name(.) = 'class' or name(.) = 'record-type' or name(.) = 'value-type'"/>

		<xsl:if test="$syn">
			<span class="annot">
				<xsl:text disable-output-escaping="yes"> &amp;nbsp;syn </xsl:text>
			</span>
			<xsl:for-each select="$syn">
				<xsl:if test="@hidden = 'yes'">
					<xsl:text disable-output-escaping="yes">&lt;span hidden="yes"&gt;</xsl:text>
				</xsl:if>
				<span class="name">
					<xsl:choose>
						<xsl:when test="$isClass">
							<xsl:call-template name="transform-class">
								<xsl:with-param name="text" select="@name"/>
							</xsl:call-template>
						</xsl:when>
						<xsl:otherwise>
							<xsl:call-template name="transform-name">
								<xsl:with-param name="text" select="@name"/>
							</xsl:call-template>
						</xsl:otherwise>
					</xsl:choose>
				</span>
				<xsl:if test="position() != last()"><xsl:text>, </xsl:text></xsl:if>
				<xsl:if test="@hidden = 'yes'">
					<xsl:text disable-output-escaping="yes">&lt;/span&gt;</xsl:text>
				</xsl:if>
			</xsl:for-each>
		</xsl:if>
	</xsl:template>

</xsl:stylesheet>
